Version: Unity 6.0 (6000.0)
语言 : 中文
Unity 如何使用序列化
序列化最佳实践

JSON 序列化

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

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

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

此代码段定义了一个包含三个变量(__leveltimeElapsed__ 以及 __playerName__)的普通 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 序列化程序进行处理时,需要遵循的规则和限制与检视面板中相同:Unity 只序列化字段;不支持类似 Dictionary<> 的类型。

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

仅在编辑器中存在一个并行 API,即 EditorJsonUtility,可以让您将派生于 UnityEngine.Object 的对象序列化为 JSON,反之亦可。这样生成的 JSON 将包含与对象的 YAML 表示相同的数据。

JsonUtilityEditorJsonUtility 都是实用程序类,可用于按 Unity 序列化规则将对象序列化为 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 如何使用序列化
序列化最佳实践