序列化程序何时可能表现异常?自定义类的行为类似于结构
对于不是从 UnityEngine.Object 派生的自定义类unity 序列化什么意思,Unity 按内联值序列化它们,类似于结构体的序列化方式。 如果您将自定义类实例的引用存储在多个不同的字段中,则它们在序列化时将成为单独的对象。 然后,当 Unity 反序列化这些字段时,它们将包含具有相同数据的不同对象。
当您需要序列化带有引用的复杂对象图时,不要让 Unity 自动序列化对象。 相反,应该使用 ISerializationCallbackReceiver 手动序列化它们。 这可以防止 Unity 从对象引用创建多个对象。 有关详细信息,请参阅 ISerializationCallbackReceiver 的文档。
这种情况仅适用于自定义类。 Unity“内联”序列化自定义类,因为这些类的数据成为使用这些类的 MonoBehaviour 或 ScriptableObject 的完整序列化数据的一部分。 当字段引用从 UnityEngine.Object 派生的类(例如,public Camera myCamera)时,Unity 会将实际引用序列化为相机 UnityEngine.Object。 如果脚本派生自 MonoBehaviour 或 ScriptableObject(均派生自 UnityEngine.Object),则相同的序列化原则适用于脚本的实例。
自定义类不支持null
考虑使用以下脚本反序列化 MonoBehaviour 时进行了多少次分配。
class Test : MonoBehaviour
{
public Trouble t;
}
[Serializable]
class Trouble
{
public Trouble t1;
public Trouble t2;
public Trouble t3;
}
发生以下分配并不奇怪:测试对象的分配。 此外,看到两种分配也就不足为奇了:一种分配给 Test 对象,另一种分配给 Trouble 对象。
然而,Unity 实际上进行了超过一千次分配。 序列化器不支持 null。 如果序列化程序序列化一个对象并且某个字段为 null创作人,则 Unity 将实例化该类型的新对象并序列化该对象。 显然这可能会导致无限循环3D道具,因此深度限制为七个级别。 当达到此限制时,Unity 将停止序列化具有自定义类、结构、列表或数组类型的字段。
由于 Unity 的许多子系统都是构建在序列化系统之上的,因此测试 MonoBehaviour 的这种异常大的序列化流会导致所有这些子系统的执行速度比所需的速度慢。
不支持多态性
如果您有公共 Animal[] 动物并输入 Dog、Cat 和 Giraffe 的实例,则序列化后您将拥有三个 Animal 实例。
解决此限制的一种方法是认识到它仅适用于内联序列化的自定义类。 对其他 UnityEngine.Object 的引用被序列化为实际引用unity 序列化什么意思,并且对于这些情况,多态性确实有效。 您可以创建 ScriptableObject 派生类或另一个 MonoBehaviour 派生类并引用该类。 这样做的缺点是您需要将 Monobehaviour 或脚本对象存储在某处,并且无法有效地内联序列化。
设置这些限制的原因是序列化系统的核心基础之一是提前了解对象的数据流布局; 它取决于类的字段类型,而不取决于字段中存储的具体内容。
提示序列化的优化应用
您可以组织数据以确保 Unity 序列化的最佳使用。
使编辑器代码可热重载
重新加载脚本时,Unity 会序列化并存储所有加载脚本中的所有变量。 重新加载脚本后,Unity会将它们恢复到序列化之前的原始值。
重新加载脚本时,Unity 会恢复所有满足序列化要求的变量(包括私有变量),即使该变量没有 SerializeField 属性。 在某些情况下,有必要故意阻止私有变量的恢复:例如,如果您希望从脚本重新加载后引用为空。 在这种情况下,请使用 NonSerialized 属性。
Unity永远不会恢复静态变量,因此不要将静态变量用于重新加载脚本后需要保留的状态。
• 2017-05-15 页面修订
在启动时运行编辑器脚本代码
内置序列化
文章来源:https://docs.unity3d.com/cn/2020.3/Manual/script-Serialization.html