Unity使用JsonUtility保存ScriptableObject后加载引用丢失问题
问题核心原因
你的保存逻辑的核心问题是:Unity的JsonUtility不支持直接序列化ScriptableObject类型的资源引用。
当你调用JsonUtility.ToJson序列化InventoryList时,列表中存储的KeyObject、HealthPotion、ScrollObject这些ScriptableObject实例,只会被序列化为当前运行时的临时实例ID,而非资源本身的固定标识。重启Unity后,所有资源的运行时实例ID会被重新分配,加载时旧ID无法匹配到新的实例,自然所有引用都会变成None。
修复方案
你需要调整存档的存储逻辑,不要直接存储ScriptableObject引用:
- 给所有物品ScriptableObject添加固定唯一标识:
比如在IItemsCollect接口中定义string ItemId属性,每个物品配置的ItemId固定不变,不会随Unity重启改变。 - 拆分存档数据和运行时数据:
不要直接序列化InventoryList这个ScriptableObject,单独做一个纯数据(POCO)类用于存档:[System.Serializable] public class InventorySaveData { public List<string> keyIds; public List<string> healingGoodsIds; public List<string> scrollIds; } - 实现全局物品索引库:
做一个静态物品管理类,启动时加载项目中所有物品ScriptableObject,按ItemId建立字典索引,方便通过ID快速找到对应的物品实例。 - 调整存取逻辑:
- 保存时:遍历当前背包中的物品实例,收集所有物品的
ItemId存入InventorySaveData,再序列化这个纯数据类写入文件。 - 加载时:先读取Json反序列化为
InventorySaveData,再根据里面的ID去物品索引库中取出对应的物品实例,赋值到运行时用的InventoryList列表中。
- 保存时:遍历当前背包中的物品实例,收集所有物品的
额外注意
ScriptableObject的设计定位是存储静态配置数据,不适合直接作为可变的运行时存档容器,拆分配置数据和存档数据可以避免很多后续序列化问题。
内容的提问来源于stack exchange,提问作者Heda
相关产品推荐
相关产品推荐

