【问题标题】:Serialization misbehave when closing Unity关闭 Unity 时序列化行为异常
【发布时间】:2015-06-18 15:51:28
【问题描述】:

我正在使用 ISerializationCallbackReceiver 序列化我的自定义相关数据,遵循教程 http://blogs.unity3d.com/2014/06/24/serialization-in-unity/ 关于图形节点的序列化调整它以满足我的需要。

当我在开发脚本时热交换代码时,我的序列化工作正常。但是一旦我保存了场景,关闭 Unity 并再次重新加载项目,我的数据就会被一些虚假的数据反序列化。

[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]

这是我正在反序列化的日志。 Unity 在 17:23:45-17:24:00 之间重新启动,如您所见,它没有从我序列化的相同数据(第 01 和 02 行)反序列化(第 03 和 04 行)。

当我保存场景时,我通常会记录第 01 行和第 02 行。

但是,当我打开 Unity 时这些“行”被反序列化时,我得到第 03 行和第 04 行,正如您所见,第 03 行“描述”与第 01 行不同,并且第 04 行缺少除“fqcn”字段之外的所有内容第 02 行。

日志尽可能精确(我正在将它们写入文件),因此这些序列化行 01 和 02 应该是 Unity 在关闭时对我的数据执行的最后一件事...

现在我迷茫了……

  1. 热交换代码时,序列化工作正常
  2. 重新启动 Unity 时无法正常工作...(最糟糕的是它只“丢弃”了一些信息)

任何提示我可能做错了什么?

(同样的情况发生在超过 3 个项目......只有第一个项目是正确的)

P.S.:资产序列化设置为“混合”还是“强制文本”都没有关系。

如果我有“MIXED”,那么场景文件中的数据如下所示:

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Ż        

如您所见,序列化数据不存在,只比较stepsData.Array.data[0]和stepsData.Array.data[1]

如果我有“强制文本”,那么场景文件中的数据如下所示(实际上更糟):

- 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}

嗯嗯,里面发生了什么?

【问题讨论】:

    标签: serialization unity3d


    【解决方案1】:

    啊啊!

    诀窍是调用 EditorUtility.SetDirty(gameObject) 每次都发生任何变化,正如本页所述:http://docs.unity3d.com/ScriptReference/EditorUtility.SetDirty.html

    Unity 在内部使用 dirty flag找出资产何时发生更改并需要保存到磁盘

    例如如果您修改预制件的 MonoBehaviour 或 ScriptableObject 变量,您必须告诉 Unity 该值已更改。每当属性更改时,Unity 内置组件都会在内部调用 SetDirty。 MonoBehaviourScriptableObject 不要这样做 自动所以如果你想保存你的值,你需要调用 SetDirty。

    因此,每当您按照 http://docs.unity3d.com/Manual/editor-CustomEditors.html 创建自定义编辑器时,请务必使用该技巧:

    GUI.changed = false;
    
    // do you're edit code here
    
    if (GUI.changed) SetDirty(yourGameObjectThatHasJustChanged);
    

    希望这可以节省某人的时间:-)

    干杯!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-02
      • 2011-11-29
      • 1970-01-01
      相关资源
      最近更新 更多