Unity 脚本序列化完全指南:原理、规则与实战技巧
2026/8/23 13:42:10 网站建设 项目流程

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 属性的可以序列化
  • staticconstreadonly的可以被序列化

简单字段类型可以被序列化:

  • 自定义的非泛型、非抽象的类,且有Serializable属性可以被序列化
  • 自定义的结构体 structs,带有Serializable属性可以被序列化
  • 引用继承自 UnityEngine.Object 的对象可以被序列化
  • 基本数据类型(intfloatdoubleboolstring等)
  • 枚举类型(Enum types)
  • 下面 Unity 内置的类型可以被序列化:Vector2Vector3Vector4RectQuaternionMatrix4x4ColorColor32LayerMaskAnimationCurveGradientRectOffsetGUIStyle
  • 对于私有字段,在加载脚本的时候是序列化的,被载入了值,在外部是不能够对其序列化的。要想在外部对其序列化,要加上SerializeField属性

含有上面类型的数组和列表可以被序列化,字典不可以被序列化。

Note:Unity 不支持多级序列化,比如多维数组、交叉数组、嵌套类型。如果你想序列化这些,有两种方法:一个是把嵌套类型封装到类或结构体内;第二个是实现 ISerializationCallbackReceiver 的回调函数,后面有介绍。

6. 序列化的技巧

  • 声明变量,目的是让 Unity 序列化尽可能小的数据集。这样做的主要目的不是为了节省计算机硬盘上的空间,而是确保您可以与项目的前一个版本保持向后兼容。如果您使用大量的序列化数据集,那么在开发的后期,向后兼容性会变得更加困难。

  • 不要序列化重复的数据或缓存的数据。这对向后兼容性造成了重大问题:它有很高的出错风险,因为数据太容易失去同步。

  • 序列化数据独立于数据本身,仅依赖于脚本中公开的内容。引用其他对象的唯一方式是通过继承自 UnityEngine.Object 的类。这些类是完全独立的;它们只相互引用,而不嵌入内容。

7. 补充:序列化与性能优化

理解 Unity 序列化机制对性能优化至关重要。以下是一些补充知识:

  • 序列化开销:Unity 在编辑器模式下每次脚本编译或属性面板刷新时都会执行序列化,频繁的序列化操作会带来一定的 CPU 开销。因此,合理控制序列化字段的数量和复杂度,有助于提升编辑器响应速度,同时也会影响反序列化时的加载速度,体现在切换场景,加载prefab的时候
  • 避免序列化敏感数据:序列化数据会以明文形式存储在场景或 Prefab 文件中,因此不应将密码、密钥等敏感信息放入可序列化字段中。
  • 使用[NonSerialized]排除字段:对于不需要序列化的 public 字段,可以使用[NonSerialized]特性显式排除,避免不必要的序列化开销。
  • 自定义序列化回调:通过实现ISerializationCallbackReceiver接口,可以在序列化和反序列化前后执行自定义逻辑,例如对字典进行手动序列化,或对数据进行校验和修复。
  • 版本兼容性:在项目迭代过程中,新增或删除序列化字段会影响旧数据的兼容性。建议在修改字段时使用[FormerlySerializedAs]特性保留旧字段名映射,确保旧数据能够正确迁移。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询