Unity3D 序列化机制:引擎内的应用场景和基本原理

Unity3D 的序列化机制是其核心功能之一,用于在编辑器和运行时之间持久化数据、管理场景状态、处理预制体(Prefab)以及实现跨平台兼容性。以下是其应用场景和基本原理的详细解析:

对惹,这里有一个游戏开发交流小组,希望大家可以点击进来一起交流一下开发经验呀!

一、应用场景

场景(Scene)与预制体(Prefab)的保存与加载

Unity 使用序列化将场景中的 GameObject、组件(Component)及其属性保存为文本或二进制格式(如 .unity 场景文件或 .prefab 文件)。

预制体的实例化和修改(如覆盖属性)依赖序列化机制。

Inspector 面板的编辑

在编辑器中,组件的公有字段(或标记了 [SerializeField] 的私有字段)通过序列化机制暴露到 Inspector 面板,修改后的值会被序列化保存。

ScriptableObject 数据持久化

ScriptableObject 的数据通过序列化存储为 .asset 文件,适用于游戏配置(如技能、物品属性)。

资源热更新与跨平台兼容

AssetBundle 中的资源(如材质、动画)通过序列化实现跨平台兼容,确保不同平台加载时数据格式正确。

运行时状态持久化

游戏存档(如玩家进度、物品栏)可通过序列化(如 JsonUtility 或 BinaryFormatter)保存到本地文件。

二、基本原理

1. 序列化的条件

Unity 的序列化遵循以下规则:

自动序列化的字段

public 字段(除非标记 [NonSerialized])。

标记了 [SerializeField] 的私有/受保护字段。

不序列化的字段

属性(Property)、静态字段、未标记 [SerializeField] 的私有字段。

标记了 [NonSerialized] 的字段。

2. 序列化流程

编辑器序列化

当场景或预制体保存时,Unity 将 GameObject 的层级结构和组件属性转换为 YAML 格式文本(可读性高)。

示例:一个 Transform 组件的序列化结果:

Transform:

  m_ObjectHideFlags: 0

  m_Position: {x: 0, y: 0, z: 0}

  m_Rotation: {x: 0, y: 0, z: 0, w: 1}

运行时序列化

使用 JsonUtility.ToJson() 或 BinaryFormatter 将对象转换为字符串或二进制数据。

3. 序列化深度

Unity 支持深度序列化,递归处理对象及其子属性。

例外

引用类型(如 UnityEngine.Object 派生类)会被序列化为元数据(如 GUID 和文件ID),而非完整对象。

循环引用可能导致序列化失败。

4. 自定义序列化

通过接口 ISerializationCallbackReceiver,开发者可以在序列化前后执行逻辑:

public class CustomData : MonoBehaviour, ISerializationCallbackReceiver

{

    public Dictionary<string, int> stats = new Dictionary<string, int>();

    // 序列化前将 Dictionary 转换为 List

    [SerializeField] private List<string> _keys;

    [SerializeField] private List<int> _values;

    public void OnBeforeSerialize()

    {

        _keys = new List<string>(stats.Keys);

        _values = new List<int>(stats.Values);

    }

    public void OnAfterDeserialize()

    {

        stats = new Dictionary<string, int>();

        for (int i = 0; i < _keys.Count; i++)

            stats.Add(_keys[i], _values[i]);

    }

}

三、技术细节与注意事项

版本兼容性

修改类结构(如删除字段)可能导致反序列化失败,旧数据可能丢失。

通过 [FormerlySerializedAs("oldFieldName")] 标记字段重命名,兼容旧数据。

性能优化

避免频繁序列化大型数据结构(如长列表),尤其在移动端。

使用 [Serializable] 标记自定义结构体或类以支持序列化。

不可序列化的类型

Unity 无法序列化接口(interface)、委托(delegate)或非 UnityEngine.Object 派生类。

解决方法:将接口转换为具体类,或使用 ScriptableObject 封装。

Prefab 差异序列化

预制体实例的属性覆盖(如修改 Transform 的位置)通过序列化差异实现,保存为“覆盖”数据而非完整副本。

四、调试与工具

查看序列化数据

在 Unity 编辑器中选择 Assets > Open C# Project,查看 .meta 文件或 YAML 格式的预制体/场景文件。

序列化检查工具

使用 UnityEditor.Serialization 命名空间中的工具(如 SerializedObject 和 SerializedProperty)在 Editor 脚本中调试序列化数据。

五、总结

Unity 的序列化机制是其数据驱动的核心,理解其规则和限制能帮助开发者:

避免数据丢失(如字段未正确序列化)。

优化资源管理(如合理使用 ScriptableObject)。

实现灵活的自定义数据持久化方案。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容