Version: 6000.3
语言: 中文
Unity 如何使用序列化
序列化最佳做法

JSON 序列化

使用 JsonUtility 类将 Unity 对象转换为 JSON 格式或从 JSON 格式转换对象。例如,您可以使用 JSON 序列化与 Web 服务交互,或者轻松地将数据打包和解压缩为基于文本的格式。

JSON 序列化使用“结构化”JSON 的概念:您创建一个类或结构来描述要在 JSON 数据中存储的变量。例如:

[Serializable]
public class MyClass
{
    public int level;
    public float timeElapsed;
    public string playerName;
}

这定义了一个包含三个变量(leveltimeElapsedplayerName)的普通 C# 类,并使用Serializable属性,以便使用 JSON 序列化程序。要创建类的实例,您可以使用如下内容:

MyClass myObject = new MyClass();
myObject.level = 1;
myObject.timeElapsed = 47.5f;
myObject.playerName = "Dr Charles Francis";

然后使用 JsonUtility.ToJson 方法将其序列化(转换为)JSON 格式:

string json = JsonUtility.ToJson(myObject);
// json now contains: '{"level":1,"timeElapsed":47.5,"playerName":"Dr Charles Francis"}'

若要将 JSON 转换回对象,请使用 JsonUtility.FromJson

myObject = JsonUtility.FromJson<MyClass>(json);

这将创建一个MyClass并使用 JSON 数据在其上设置值。如果 JSON 数据包含未映射到MyClass,则序列化程序将忽略这些值。如果 JSON 数据缺少MyClass,则序列化程序将这些字段的构造值保留在返回的对象中。

使用 JSON 覆盖对象

您还可以在现有对象上反序列化 JSON 数据,这会覆盖任何现有数据:

JsonUtility.FromJsonOverwrite(json, myObject);

如果 JSON 数据不包含字段的值,则序列化程序不会更改该字段的值。此方法允许您通过重用以前创建的对象来将分配保持在最低限度。它还允许您通过故意使用仅包含一小部分字段的 JSON 覆盖对象来“修补”对象。

警告:JSON 序列化器 API 支持 MonoBehaviourScriptableObject 子类以及普通结构和类。但是,当将 JSON 反序列化为MonoBehaviourScriptableObject,则必须使用 FromJsonOverwrite 方法。如果您尝试使用 FromJson,Unity 会抛出异常,因为不支持此行为。

支持的类型

JSON 序列化器 API 支持任何MonoBehaviour亚纲ScriptableObject子类,或普通类或结构体,并带有[Serializable]属性。将对象传入标准 Unity 序列化程序进行处理时,与 Inspector 中相同的规则和限制适用:Unity 仅序列化字段;以及像Dictionary<>不支持。

Unity 不支持将其他类型直接传递给 API,例如原始类型或数组。如果您需要转换这些,请将它们包装在classstruct某种。

仅在编辑器中,有一个并行 API EditorJsonUtility,它允许您将派生自 UnityEngine.Object 的任何对象序列化为 JSON 或从 JSON 序列化。这将生成包含与对象的 YAML 表示相同的数据的 JSON。

JsonUtilityEditorJsonUtility 是实用程序类,用于使用 Unity 序列化规则将对象序列化到 JSON 的字符串格式或从 JSON 的字符串格式序列化对象。如果需要通过代码作 JSON 数据,或序列化 Unity 序列化不支持的数据结构,可以使用常规用途 .NET JSON 库作为 JsonUtility API 的配套。

性能

基准测试表明,JsonUtility 比流行的 .NET JSON 解决方案快得多,尽管此类在某些情况下提供的功能较少。

垃圾回收 (GC) 的内存使用量最低:

  • ToJson 仅为返回的字符串分配 GC 内存。
  • FromJson 仅为返回的对象以及所需的任何子对象分配 GC 内存(例如,如果您反序列化包含数组的对象,则 Unity 会为该数组分配 GC 内存)。
  • FromJsonOverwrite 仅根据写入字段(例如字符串和数组)的需要分配 GC 内存。这意味着,如果 JSON 覆盖的所有字段都是值类型,则 Unity 根本不会分配任何 GC 内存。

您可以从后台线程使用 JsonUtility API。但是,与任何多线程代码一样,请注意不要在另一个线程序列化或反序列化一个线程上访问或更改一个线程上的对象。

控制 ToJson() 的输出

ToJson 方法支持漂亮地打印 JSON 输出。默认情况下它是关闭的,但您可以通过传递true作为第二个参数。

您可以使用[NonSerialized]属性。

将 FromJson() 与未知类型一起使用

如果您事先不知道对象的类型,请将 JSON 反序列化为包含“公共”字段的类或结构,然后使用这些字段的值来计算出您想要的实际类型。然后第二次反序列化为该类型。

Unity 如何使用序列化
序列化最佳做法