You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何制作可在运行时保存Unity特定对象及组件值的存档系统

Unity 复杂对象与集合的存档解决方案

问题根源

多数通用存档工具只支持基础类型,本质是因为Unity的内置值类型(Vector、Quaternion等)、集合(字典)以及场景对象(GameObject/组件)无法被常规序列化工具直接处理:

  • JsonUtility 对非Unity原生支持的类型(比如字典)兼容性极差,且需要类和字段都标记[Serializable];
  • Newtonsoft.Json 不识别Unity对象的内部结构,直接序列化GameObject/组件会生成一堆无效数据,甚至抛出异常。

分步解决方法

1. 处理Unity值类型(Vector3、Color等)

给Newtonsoft.Json写自定义转换器,把复杂值类型拆成基础字段序列化:

public class Vector3Converter : JsonConverter<Vector3>
{
    public override void WriteJson(JsonWriter writer, Vector3 value, JsonSerializer serializer)
    {
        writer.WriteStartObject();
        writer.WritePropertyName("x");
        writer.WriteValue(value.x);
        writer.WritePropertyName("y");
        writer.WriteValue(value.y);
        writer.WritePropertyName("z");
        writer.WriteValue(value.z);
        writer.WriteEndObject();
    }

    public override Vector3 ReadJson(JsonReader reader, Type objectType, Vector3 existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        return new Vector3(
            (float)jo["x"],
            (float)jo["y"],
            (float)jo["z"]);
    }
}

使用时把转换器加入序列化配置:

var jsonSettings = new JsonSerializerSettings();
jsonSettings.Converters.Add(new Vector3Converter());
string serializedData = JsonConvert.SerializeObject(yourSaveData, jsonSettings);

2. 处理字典与自定义集合

JsonUtility 不支持原生字典,需要封装可序列化的字典类:

[Serializable]
public class SerializableDict<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver
{
    [SerializeField] private List<TKey> _keys = new();
    [SerializeField] private List<TValue> _values = new();

    public void OnBeforeSerialize()
    {
        _keys.Clear();
        _values.Clear();
        foreach (var pair in this)
        {
            _keys.Add(pair.Key);
            _values.Add(pair.Value);
        }
    }

    public void OnAfterDeserialize()
    {
        Clear();
        for (int i = 0; i < Math.Min(_keys.Count, _values.Count); i++)
        {
            Add(_keys[i], _values[i]);
        }
    }
}

Newtonsoft.Json原生支持字典,但如果字典里存Unity值类型,要配合上面的自定义转换器使用。

3. 处理GameObject/组件(核心原则:不直接序列化引用)

Unity场景对象是动态实例,直接序列化会导致存档无法跨场景/版本兼容,正确做法是只序列化关键业务数据:

  • 先定义纯数据类,存储需要存档的参数:
    [Serializable]
    public class PlayerSaveData
    {
        public Vector3 position;
        public Quaternion rotation;
        public int currentHealth;
        public SerializableDict<string, int> inventory; // 用自定义可序列化字典
    }
    
  • 存档时从组件提取数据,读档时把数据赋值回对象:
    // 存档逻辑
    var saveData = new PlayerSaveData();
    saveData.position = playerTransform.position;
    saveData.currentHealth = playerHealthComp.currentHealth;
    string json = JsonConvert.SerializeObject(saveData, jsonSettings);
    File.WriteAllText(Application.persistentDataPath + "/playerSave.json", json);
    
    // 读档逻辑
    string loadedJson = File.ReadAllText(Application.persistentDataPath + "/playerSave.json");
    var loadedData = JsonConvert.DeserializeObject<PlayerSaveData>(loadedJson, jsonSettings);
    playerTransform.position = loadedData.position;
    playerHealthComp.currentHealth = loadedData.currentHealth;
    

4. 现成工具替代

如果不想自己写逻辑,Asset Store里的Easy Save 3或Save Game Pro都原生支持Unity值类型、集合,还封装了场景对象的安全序列化逻辑,不用额外写转换器。

避坑提醒

  • 永远不要直接序列化MonoBehaviour、GameObject这类Unity对象,只序列化纯数据类;
  • JsonUtility 要求序列化类必须标记[Serializable],私有字段要加[SerializeField]才能被序列化;
  • Newtonsoft.Json序列化时,用[JsonIgnore]标记不需要存档的字段,避免生成冗余数据。

内容的提问来源于stack exchange,提问作者Yasser Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 00:57:38