版本:Unity 6 (6000.0)
语言:英语
自定义序列化
JSON 序列化

Unity 如何使用序列化

保存和加载

Unity 使用序列化将场景场景包含游戏的环境和菜单。将每个独特的场景文件视为一个独特的关卡。在每个场景中,您放置环境、障碍物和装饰,本质上是在构建游戏的部分内容。 更多信息
参见 词汇表
资源任何可在游戏中或项目中使用的媒体或数据。资源可能来自 Unity 外部创建的文件,例如 3D 模型、音频文件或图像。您也可以在 Unity 中创建一些资源类型,例如动画控制器、音频混音器或渲染纹理。 更多信息
参见 词汇表
资源包加载到设备的内存中,并从设备的内存中保存。这包括存储在您自己的脚本 API 对象中的数据,例如MonoBehaviour组件和ScriptableObjects

Unity 编辑器中的许多功能都建立在核心序列化系统之上。在序列化方面需要特别注意的是检查器窗口和热重载。

检查器窗口

检查器一个 Unity 窗口,显示有关当前选定游戏对象、资源或项目设置的信息,允许您检查和编辑值。 更多信息
参见 词汇表
窗口显示被检查对象的序列化字段的值。当您在检查器中更改值时,检查器会更新序列化数据并触发反序列化,从而更新被检查对象。

这同样适用于内置 Unity 对象和脚本对象(例如从 MonoBehaviour 派生的类)。

当您在检查器窗口中查看或更改值时,Unity 不会调用任何 C# 属性获取器和设置器。相反,Unity 会直接访问序列化的后备字段。

热重载

脚本代码的热重载是作为资源数据库刷新的一部分执行的。它指的是在编辑器运行时直接重新加载和应用代码更改的过程,而无需重新启动编辑器。有关更多信息,请参阅刷新资源数据库热重载

注意:热重载是一种特殊的序列化情况。与其他序列化情况不同,Unity 在重新加载时默认序列化私有字段,即使它们没有SerializeField属性。

当 Unity 重新加载脚本一段代码,允许您创建自己的组件,触发游戏事件,随着时间的推移修改组件属性,并以您喜欢的任何方式响应用户输入。 更多信息
参见 词汇表

  1. Unity 会序列化并存储所有已加载脚本中的所有变量。
  2. Unity 会将其恢复为原始的序列化前值
    • Unity 会恢复所有变量——包括私有变量——这些变量满足序列化要求,即使变量没有 [SerializeField] 属性。有时,您需要阻止 Unity 恢复私有变量,例如,如果您希望在从脚本重新加载后引用为 null。在这种情况下,使用[field: NonSerialized]属性。
    • Unity 从不恢复静态变量,因此不要将静态变量用于在 Unity 重新加载脚本后需要保留的状态,因为重新加载过程会将其丢弃。

预制件

一个预制件一种资源类型,允许您存储一个完整的游戏对象,包括组件和属性。预制件充当模板,您可以从中在场景中创建新的对象实例。 更多信息
参见 词汇表
是一个或多个游戏对象Unity 场景中的基本对象,可以代表角色、道具、场景、摄像机、路点等。游戏对象的功能由附加在其上的组件定义。 更多信息
参见 词汇表
组件游戏对象的组成部分。一个游戏对象可以包含任意数量的组件。Unity 有许多内置组件,您也可以通过编写从 MonoBehaviour 继承的脚本创建自己的组件。 更多信息
参见 词汇表
的序列化数据。预制件实例包含对预制件源的引用和对它的修改列表。修改是 Unity 需要对预制件源执行的操作,以创建该特定的预制件实例。

预制件实例仅在您在 Unity 编辑器中编辑项目时存在。Unity 编辑器会从其两组序列化数据(预制件源和预制件实例的修改)中实例化一个游戏对象。

实例化

当您在场景中存在的任何内容(例如预制件或游戏对象)上调用Instantiate

  1. Unity 会对其进行序列化。这在运行时和编辑器中都会发生。Unity 可以序列化从 UnityEngine.Object 派生的所有内容。
  2. Unity 会创建一个新的游戏对象并将其数据反序列化到新的游戏对象上。
  3. Unity 会在不同的变体中运行相同的序列化代码以报告它引用的其他 UnityEngine.Objects。它会检查所有引用的 UnityEngine.Objects 以确定它们是否属于 Unity 实例化的数据的一部分。如果引用指向外部内容(例如纹理),Unity 会保留该引用。如果引用指向内部内容(例如子游戏对象),Unity 会将引用修补到相应的副本。

卸载未使用的资源

EditorUtility.UnloadUnusedAssetsImmediate 是 Unity 的原生垃圾收集器,它与标准 C# 垃圾收集器有不同的用途。它在您加载场景后运行,并检查它不再引用的对象(例如纹理),并安全地卸载它们。Unity 的原生垃圾收集器会以一种变体形式运行序列化器,其中对象会报告对外部 UnityEngine.Objects 的所有引用。这就是纹理在场景中使用,垃圾收集器会在下一个场景中卸载它们的方式。

编辑器和运行时序列化之间的差异

大多数序列化发生在编辑器中,而反序列化是运行时的重点。Unity 只在编辑器中序列化一些功能,而它可以在编辑器和运行时序列化其他功能。

功能 编辑器 运行时
二进制格式的资源 支持读写 支持读取
YAML 格式的资源 支持读写 不支持
保存场景、预制件和其他资源 支持,除非处于播放模式 不支持
使用JsonUtility序列化单个对象 使用 JsonUtility 支持读写。

使用 EditorJsonUtility 支持其他类型的对象
使用 JsonUtility 支持读写
SerializeReference 支持 支持
ISerializationCallbackReceiver 支持 支持
FormerlySerializedAs 支持 不支持

对象可以具有仅编辑器序列化的附加字段,例如,当您在 UNITY_EDITOR 脚本符号中声明字段时

public class SerializeRules : MonoBehaviour
{
#if UNITY_EDITOR
public int m_intEditorOnly;
#endif
}

在前面的示例中,m_intEditorOnly 字段仅在编辑器中序列化,并且不包含在构建中。这使您能够通过从构建中省略仅在编辑器中需要的數據來節省内存。使用该字段的任何代码也需要进行条件编译,例如在 #if UNITY_EDITOR 块中,以便该类可以在构建时进行编译。

编辑器不支持具有 Unity 仅在运行时序列化的字段的对象(例如,当您在 UNITY_STANDALONE 指令中声明字段时)。

其他资源

自定义序列化
JSON 序列化