Unity 脚本序列化完全指南:原理、规则与实战技巧

📅 2026/8/23 13:42:20
Unity 脚本序列化完全指南:原理、规则与实战技巧
1. 序列化序列化是Unity中把数据存储到磁盘中的过程。比如.unity/.prefab这些都是磁盘文件里面包含了序列化的数据存储在磁盘上运行时反序列化这些文件赋值给变量。而非序列化的变量的值在C#编译器IL阶段就赋值上了或者在运行时赋值不在磁盘上存储也就少了反序列化的时间。2. 什么是热重载在编辑器下创建或修改脚本后能够立即生效的过程不需要重新打开VS 或者 Unity也不需要重新编译。更改脚本中的可序列化的变量值时Unity 会先存储到硬盘上然后加载赋值。那些不能序列化的变量值就丢失了因为磁盘上没有存它的值就还是初始值。3. 保存和加载Unity 使用序列化从硬盘上加载 Scenes、Assets、AssetBundles 等资源。这也包括脚本中保存的变量数据比如 MonoBehaviour 组件和 ScriptableObjects。4. 属性面板当在属性面板上更改游戏物体的属性值时Unity 会先序列化该数据然后再把它显示出来。属性面板上更改了之后直接序列化数据覆盖原来的值和脚本没有任何关系即使脚本中该变量有 get/set 属性也不会执行。脚本中定义了变量值在属性面板上给改了之后使用的是面板上的值因为面板是后序列化的。5. 序列化规则Unity 中的序列化是实时运行的所以对性能是有影响的。下面是一些序列化的条件是public或者是 private 但是有 SerializeField 属性的可以序列化非static、const、readonly的可以被序列化简单字段类型可以被序列化自定义的非泛型、非抽象的类且有Serializable属性可以被序列化自定义的结构体 structs带有Serializable属性可以被序列化引用继承自 UnityEngine.Object 的对象可以被序列化基本数据类型int、float、double、bool、string等枚举类型Enum types下面 Unity 内置的类型可以被序列化Vector2、Vector3、Vector4、Rect、Quaternion、Matrix4x4、Color、Color32、LayerMask、AnimationCurve、Gradient、RectOffset、GUIStyle对于私有字段在加载脚本的时候是序列化的被载入了值在外部是不能够对其序列化的。要想在外部对其序列化要加上SerializeField属性含有上面类型的数组和列表可以被序列化字典不可以被序列化。NoteUnity 不支持多级序列化比如多维数组、交叉数组、嵌套类型。如果你想序列化这些有两种方法一个是把嵌套类型封装到类或结构体内第二个是实现 ISerializationCallbackReceiver 的回调函数后面有介绍。6. 序列化的技巧声明变量目的是让 Unity 序列化尽可能小的数据集。这样做的主要目的不是为了节省计算机硬盘上的空间而是确保您可以与项目的前一个版本保持向后兼容。如果您使用大量的序列化数据集那么在开发的后期向后兼容性会变得更加困难。不要序列化重复的数据或缓存的数据。这对向后兼容性造成了重大问题它有很高的出错风险因为数据太容易失去同步。序列化数据独立于数据本身仅依赖于脚本中公开的内容。引用其他对象的唯一方式是通过继承自 UnityEngine.Object 的类。这些类是完全独立的它们只相互引用而不嵌入内容。7. 补充序列化与性能优化理解 Unity 序列化机制对性能优化至关重要。以下是一些补充知识序列化开销Unity 在编辑器模式下每次脚本编译或属性面板刷新时都会执行序列化频繁的序列化操作会带来一定的 CPU 开销。因此合理控制序列化字段的数量和复杂度有助于提升编辑器响应速度同时也会影响反序列化时的加载速度体现在切换场景加载prefab的时候。避免序列化敏感数据序列化数据会以明文形式存储在场景或 Prefab 文件中因此不应将密码、密钥等敏感信息放入可序列化字段中。使用[NonSerialized]排除字段对于不需要序列化的 public 字段可以使用[NonSerialized]特性显式排除避免不必要的序列化开销。自定义序列化回调通过实现ISerializationCallbackReceiver接口可以在序列化和反序列化前后执行自定义逻辑例如对字典进行手动序列化或对数据进行校验和修复。版本兼容性在项目迭代过程中新增或删除序列化字段会影响旧数据的兼容性。建议在修改字段时使用[FormerlySerializedAs]特性保留旧字段名映射确保旧数据能够正确迁移。