Reputation: 101
I'm using ISerializationCallbackReceiver to serialize my custom interrelated data following tutorial http://blogs.unity3d.com/2014/06/24/serialization-in-unity/ regarding serialization of graph nodes adjusting it to my needs.
My serialization is working fine when I'm hot swapping the code when I'm developing scripts. But once I save the scene, close Unity and reload the project again, my data is deserializing from some bogus.
[01] [17:23:43] Quest[The Sculpture and The Box|SLEEP]: Serializing QuestStepData[fqcn=experiment.questsjg.steps.GoToLocation|name=Sculpture|description=F|closedByIndex=-1|go1Present=True|go1=sculptures_01_02 (UnityEngine.GameObject)|go2Present=True|go2=[1] Go To Location Point (Sculpture) (UnityEngine.GameObject)|f1=8]
[02] [17:23:43] Quest[The Sculpture and The Box|SLEEP]: Serializing QuestStepData[fqcn=experiment.questsjg.steps.GoToLocation|name=box|description=S|closedByIndex=-1|go1Present=True|go1=box1 (UnityEngine.GameObject)|go2Present=True|go2=[2] Go To Location Point (box) (UnityEngine.GameObject)|f1=4]
[03] [17:24:09] Quest[The Sculpture and The Box|SLEEP]: Deserializing QuestStepData[fqcn=experiment.questsjg.steps.GoToLocation|name=Sculpture|description=|closedByIndex=-1|go1Present=True|go1= (UnityEngine.GameObject)|go2Present=True|go2= (UnityEngine.GameObject)|f1=8]
[04] [17:24:09] Quest[The Sculpture and The Box|SLEEP]: Deserializing QuestStepData[fqcn=experiment.questsjg.steps.GoToLocation|name=|description=|closedByIndex=-1|go1Present=False|go2Present=False|f1=10]
Here is a log of what I'm de/serializing. Unity got restarted between 17:23:45-17:24:00 and as you can see it did not deserialize (Rows 03 and 04) from the same data I serialized (Rows 01 and 02).
When I save the scene, I typically get Rows 01 and 02 logged.
But when these "rows" gets deserialized when I open Unity, I get Rows 03 and 04 and as you can see Row 03 "description" differs from Row 01 and Row 04 is missing everything except 'fqcn' field when compared with Row 02.
Logs are as precise as they can get (I'm writing them to the file), so these serialization lines 01 and 02 should be the last thing Unity is doing with my data when closing...
Now I'm buffled...
Any hints what I might be doing wrong?
(The same happens for 3+ items... only 1st item is somehow correct)
P.S.: It does not matter whether you have Asset serialization set to "Mixed" or "Force Text".
If I have "MIXED" then data within the scene file looks like this:
The Sculpture and The Box ! NyŻ
stepsData.Array.data[0].fqcn&
experiment.questsjg.steps.GoToLocation ! NyŻ %
stepsData.Array.data[0].closedByIndex -1 ! NyŻ
stepsData.Array.data[0].f1 8 ! NyŻ
stepsData.Array.data[0].name Sculpture ! NyŻ
stepsData.Array.data[0].go1 ^ ! NyŻ "
stepsData.Array.data[0].go1Present 1 ! NyŻ
stepsData.Array.data[0].go2 *¨ ! NyŻ "
stepsData.Array.data[0].go2Present 1 ! NyŻ
stepsData.Array.data[1].fqcn&
experiment.questsjg.steps.GoToLocation ! NyŻ %
stepsData.Array.data[1].closedByIndex -1 ! NyŻ
stepsData.Array.data[1].f1 10 ! NyŻ
As you can see, serialized data are not there, just compare stepsData.Array.data[0] and stepsData.Array.data[1]
If I have "Force Text" then data within the scene file looks like this (it's actually even worse):
- target: {fileID: 11499854, guid: bd017908bdedeb24d9559a160e99a0c1, type: 2}
propertyPath: stepsData.Array.data[0].fqcn
value: quests.steps.GoToLocation
objectReference: {fileID: 0}
- target: {fileID: 11499854, guid: bd017908bdedeb24d9559a160e99a0c1, type: 2}
propertyPath: stepsData.Array.data[0].closedByIndex
value: -1
objectReference: {fileID: 0}
- target: {fileID: 11499854, guid: bd017908bdedeb24d9559a160e99a0c1, type: 2}
propertyPath: stepsData.Array.data[0].f1
value: 10
objectReference: {fileID: 0}
- target: {fileID: 11499854, guid: bd017908bdedeb24d9559a160e99a0c1, type: 2}
propertyPath: stepsData.Array.data[1].fqcn
value: quests.steps.GoToLocation
objectReference: {fileID: 0}
- target: {fileID: 11499854, guid: bd017908bdedeb24d9559a160e99a0c1, type: 2}
propertyPath: stepsData.Array.data[1].closedByIndex
value: -1
objectReference: {fileID: 0}
- target: {fileID: 11499854, guid: bd017908bdedeb24d9559a160e99a0c1, type: 2}
propertyPath: stepsData.Array.data[1].f1
value: 10
objectReference: {fileID: 0}
- target: {fileID: 107138, guid: bd017908bdedeb24d9559a160e99a0c1, type: 2}
propertyPath: m_Name
value: First Quest
objectReference: {fileID: 0}
Hmmmm, what's happening in there?
Upvotes: 1
Views: 339
Reputation: 101
Aaaa!
The trick is to call EditorUtility.SetDirty(gameObject) EVERY TIME ANYTHING CHANGES as this page states: http://docs.unity3d.com/ScriptReference/EditorUtility.SetDirty.html
Unity internally uses the dirty flag to find out when assets have changed and need to be saved to disk.
E.g. if you modify a prefab's MonoBehaviour or ScriptableObject variables, you must tell Unity that the value has changed. Unity builtin components internally call SetDirty whenever a property changes. MonoBehaviour or ScriptableObject DON'T DO this AUTOMATICALLY so if you want your value to be saved you need to call SetDirty.
Therefore, whenever you're creating your CustomEditor following http://docs.unity3d.com/Manual/editor-CustomEditors.html make sure to use the trick:
GUI.changed = false;
// do you're edit code here
if (GUI.changed) SetDirty(yourGameObjectThatHasJustChanged);
Hope this saves someone's time :-)
Cheers!
Upvotes: 0