I have made custom inspector for my class with ability to manage delegates. Everything works perfect in edit mode but when I run play mode all delegate values are reset to default. All these fields are marked with SerializeField attribute and whole class is also marked with Serializable attribute. Are delegates serializable in Unity? It is really important question as I wrote many code around this without even thinking that I should have tested delegate serialization at first
No. If you don't see it in the Inspector, and it's not using [HideInInspector], then it's not serialized, even if you give it [SerializeField] or make it public. All of my delegates and events are set up in Awake, for this reason. (Unless of course they'll be reassigned during gameplay, but even then, they'll get an initial value in Awake.)
That's not entirely true Jessy, at lest not in 3.5 (haven't checked it before). I've managed to serialize a public delegate. The problem is that many people think that Awake is not executed after you hit play - and it is. So they assign a null value to their delegates (so as to have an initialized delegate) into awake and... well, you guess the rest. The proper way (or at least an elegant way) to do it is to have a delegate initialization method, and call it from Awake only if the delegate is null, this way it won't be initialized again during play. Something like this: public void Awake() { if (UpdateAction == null) InitializeUpdateDelegate(); } public void InitializeUpdateDelegate() { UpdateAction = RedrawCanvas; } Edit: For the record I've used the word "serialize" mistakenly last year, I confused it with "persist", as in keeping it while getting in and out of play mode. I don't see much of a reason to actually serialize (as in "between Unity sessions") a delegate, I simply initialize it with some method when applicable - but I might be wrong and you could come up with some interesting example.
I don't believe you; let's see it! I realize that many people don't RTFM, but I don't think they'd be reading this thread. Why would you bother reassigning to null?
What's the point of doing this? The Awake will only be called once: When the object is created, and never again. When you destroy the object and create a new one, you will have to assign it again, on each instance. The event will always be null in your case, when an Object is created, unless it's static. If the event is part of some other Object, it makes no sense at all to check against null, because it doesn't matter. And static events/delegates are to be threated carefully in order to prevent serious memory leaks. The only reason ever, where you must check an event against null is before calling it Code (csharp): if(UpdateAction != null) UpdateAction(...); But honestly, I don't know of any reason why someone would want to have delegates serialization in the Inspector. Maybe a Dictionary<string, Delegate> would be better for your case? You could assign a "event" string in the inspector and do something like events[myEventString] += MyAction; where myEventString is set in the inspector. http://msdn.microsoft.com/en-us/library/z4ka55h8(v=vs.100).aspx
Guess he didn't got it that Code (csharp): public void Awake() { UpdateAction = UpdateAction ?? RedrawCanvas; } is equal to Code (csharp): public void Awake() { if(UpdateAction==null) UpdateAction = RedrawCanvas; } XD
Really? I was under the impression that it meant Code (csharp): UpdateAction = UpdateAction == null ? RedrawCanvas : UpdateAction; Functionally equivalent, but I was under the impression that reassigning the same pointer is both an unnecessary use of CPU time, and less clear code. I'm also saying that UpdateAction will always be null (in the non-static case). I realize what I said could have been worded better; UpdateAction == null is the one case where there would not be an unneeded reassignment. It's complicated to talk about, because the code assumes a falsity, as far as I know.
Typically it is, but the case above is special in so far, that UpdateAction is on both sides (left and right). Also there is no reason to be concerned about a cpu cycle more or less, when this code is inside of a method which is only called once or rarely. Usually the compiler should take this into consideration that left and right side of the equal sign are the same and apply, otherwise JIT could do it (even though, Mono JIT - especially the outdated Mono used in Unity - is not as sophisticated as the .NET one).
Hmm, looking at the generated code in Reflector gives some interesting results! For the one-liner, it does indeed emit a redundant store. But the version with an "if" statement is just as long, and includes a call to the inequality operator. Ick. I guess Mono's code generation really is quite bad sometimes.
Whoa - 'unnecessary use of CPU time'? What are you on? At the very worst, assuming crappy compilers, we're copying one pointer to another. If that's going to have a measurable performance impact on your game then you need to get off of your abacus! In terms of less clear code, compared to the alternative it is much clearer. That's an entirely separate issue. If UpdateAction is always null then any method of checking for null is redundant. If it might not always be null, and you want ensure a default is assigned in the cases where it is null, the ?? operator exists.
I don't agree. The former suggests that we always plan to make an assignment; the latter says exactly what we mean. It doesn't matter that the copying is negligible; Earth creatures form habits and lifestyles, and being negligent here can lead to unintentional mass extinctions or subpar suppers. Code (csharp): UpdateAction = UpdateAction ?? RedrawCanvas; if (UpdateAction == null) UpdateAction = RedrawCanvas;
Anyone got this working in Unity 4? I've personally failed a couple of times to serialize any kind of delegate.
Actually no, I didn't mean that since, at least in Unity 3.5, in some circumstances the ?? operator simply doesn't work, you have to explicitly compare with null. That's one of those situations, and I could only find it through trial-and-error. PS.: For the record I've used the word "serialize" mistakenly last year, I confused it with "persist", as in keeping it while getting in and out of play mode. I don't see much of a reason to actually serialize (as in "between Unity sessions") a delegate, I simply initialize it with some method when applicable - but I might be wrong and you could come up with some interesting example.
1) Wow... took you a while to respond! 2) Are you sure the ?? doesn't work? I could understand if UT's stupid 'Object' equality overrides were stuffing something up - but not simple delegates.
I have a suspicion. Unity fails massively with some of the C# features in some of the builtin methods called from the native core. Let me explain - some stuff per say, cause the engine to crash, or misbehave in various and arbitrary ways without no other reason. For example I've encountered a lot of problems with default values in the Update() method. At some point I had an Update method which had a rather indirect call to a function with a default parameter - it resulted a failed compilation of the whole file. Unity just decided that it does not exist. Another example was even simpler - a direct call to a method with a default parameter ( 1 exactly ) in an Update() resulted a crash with some internal error that hadn't to do anything with the actual problem. ( I haven't done extensive testing on the subject ) I've encountered numerous problems with the ?? operator. I suspect that they get called by the Native core and that causes the errors. I've been using a parenthesis trick up till couple of weeks but that ended causing problems, too. Basically the only bullet-proof solution is using the :? instead of the ?? operator.
jedy, I don't think you're right about the null-coalescing operator. I have no troubles with it. MonoBehaviours can't use optional parameters, if that's what you're talking about.
No idea mate, just sharing some personal experience. And still it worked with me most of the time ( almost exclusively in properties ). And at times some of them just decided that working isn't an option anymore. That came after work on some code that wasn't even closely relevant to the class which fired the error, and some heavy debugging sessions followed, but to no avail. PS : If my memory serves me well - some of the MonoBehaviour component property overrides ( transform, collider etc ) did that after couple of weeks using them with the null-coalescing operator.
Since delegates can't be serialized, how would you go about doing something like this? In this example, I want to create the delegate once in the constructor and keep it around so I can reuse it instead of having to create it every time I need it. Problem is, when a field is not serialized and Unity does an asset import operation while the editor is in play mode, the field will get wiped. (This is important for editor tools because you want them to work through an asset import.) My class isn't a Monobehaviour, so no OnEnable() to run after the asset import. The best thing I can think of is to check if myCallback == null every time I use it and then recreate it. But I'd rather have a cleaner way... Code (csharp): [System.Serializable] public class MyClass { [SerializeField] private System.Action<string, object> myCallback; public MyClass() { myCallback = MyCallback; } private void MyCallback(string message, object obj) { // Code here } }
Personally I use an auto initializing properties if I decide to stick to delegates. Yet I rarely do so, because editor code looks and functions a lot cleaner if it is fully serializable. Code (csharp): [System.Serializable] public class MyClass { [SerializeField] private System.Action<string, object> myCallback; public System.Action MyCallback { get { if(myCallback == null) myCallback = Value; return myCallback; } } } [/QUOTE]
Hey all - Thought I'd share with you my solution to serializing and inspecting delegates via the inspector: uFAction! I really think there should be a powerful built-in solution for delegates and events.