Unity使用JsonUtility序列化对象时嵌套类信息丢失问题
问题根源
JsonUtility对继承自MonoBehaviour的类有特殊处理逻辑:当这类组件对象作为另一个类的字段存在时,默认只会序列化它的实例引用(instanceID),而非对象内部的属性数据——因为Unity将MonoBehaviour视为场景/预制体中的组件实例,而非普通数据容器。但单独序列化组件本身时,它会正常解析内部可序列化字段,这就是你遇到两种结果不一致的原因。
解决方法
方案1:剥离数据与逻辑(最推荐)
把Inventory的业务数据单独抽成一个普通可序列化类,让MonoBehaviour仅作为逻辑载体,SaveData只保存这个纯数据类的实例:
// 纯数据类,标记可序列化 [Serializable] public class InventoryData { public List<Item> database; public List<InventorySlot> Container; // 其他需要存档的字段 } // MonoBehaviour组件只负责逻辑,数据存在InventoryData里 public class Inventory : MonoBehaviour { public InventoryData data; void Awake() { // 初始化数据容器 data = new InventoryData(); // 这里可以初始化database、Container等数据 } // 业务逻辑中直接操作data里的字段 } // 存档类,只保存纯数据对象 [Serializable] public class SaveData { public InventoryData inventoryData; // 其他存档字段 } // 保存逻辑 public void Save() { Inventory inventory = GetComponent<Inventory>(); SaveData saveObject = new SaveData(); // 存数据类而非组件实例 saveObject.inventoryData = inventory.data; string json = JsonUtility.ToJson(saveObject); // 后续保存json到文件/PlayerPrefs等 }
方案2:手动嵌入组件序列化结果(应急方案)
如果不想修改现有结构,可以先单独序列化Inventory得到完整JSON字符串,再将这个字符串作为SaveData的字段存储:
[Serializable] public class SaveData { public string inventoryJson; // 其他存档字段 } // 保存逻辑 public void Save() { Inventory inventory = GetComponent<Inventory>(); SaveData saveObject = new SaveData(); // 单独序列化Inventory得到完整数据 saveObject.inventoryJson = JsonUtility.ToJson(inventory); string finalJson = JsonUtility.ToJson(saveObject); // 保存最终json } // 加载逻辑 public void Load() { string finalJson = // 读取的存档JSON SaveData saveObject = JsonUtility.FromJson<SaveData>(finalJson); Inventory inventory = GetComponent<Inventory>(); // 将单独的Inventory数据覆盖到组件实例 JsonUtility.FromJsonOverwrite(saveObject.inventoryJson, inventory); }
注意事项
- 所有自定义数据类(包括
InventorySlot)都必须标记[Serializable],否则JsonUtility会忽略其内部字段。 - 避免在可序列化类中直接包含Unity的Object类型(如GameObject、Component),除非你确实需要保存实例引用而非数据。
内容的提问来源于stack exchange,提问作者Gia Bảo
相关产品推荐
相关产品推荐

