Unity中向泛型列表添加指定类型对象后序列化数据丢失如何解决
问题解决:Unity ScriptableObject中多态对象列表的持久化序列化
核心问题原因
你遇到的问题本质是Unity默认的[SerializeField]不支持非ScriptableObject类型的多态序列化:当你用Activator.CreateInstance创建Jar子类实例并添加到列表后,Unity序列化时只会保存基类Jar的信息,丢失子类的类型和数据,导致编译/重启后列表为空。
解决方案代码修改
直接通过[SerializeReference]替代[SerializeField]来启用多态序列化,同时修正代码中的笔误和编辑器保存逻辑:
using System; using System.Collections.Generic; using UnityEngine; using UnityEditor; [CreateAssetMenu(fileName = "New Shelf", menuName = "Inventory/Shelf")] public class Shelf : ScriptableObject { // 用[SerializeReference]替代[SerializeField]来支持多态序列化 [SerializeReference] private List<Jar> jars = new(); public void AddUniqueJar(Type typeOfJar) { if (!typeof(Jar).IsAssignableFrom(typeOfJar) || typeOfJar.IsAbstract) { Debug.LogError("传入的类型必须是Jar的非抽象子类"); return; } // 避免重复添加同类型(按需保留) if (jars.Exists(jar => jar.GetType() == typeOfJar)) { Debug.LogWarning($"已经存在{typeOfJar.Name}类型的罐子"); return; } // 记录对象状态,支持编辑器撤销 Undo.RecordObject(this, $"Add {typeOfJar.Name}"); // 创建子类实例并添加到列表 Jar newJar = (Jar)Activator.CreateInstance(typeOfJar); jars.Add(newJar); // 标记对象为脏并保存 EditorUtility.SetDirty(this); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } } [Serializable] public abstract class Jar {} [Serializable] public class JamJar : Jar {} [Serializable] public class PickleJar : Jar {} [Serializable] public class MoneyJar : Jar {}
关键修改说明
[SerializeReference]的作用:
这个属性会让Unity序列化对象时同时存储其具体类型信息,重启或编译后能正确恢复子类实例,而不是只序列化基类数据。- 编辑器保存逻辑优化:
- 用
Undo.RecordObject记录操作,符合Unity编辑器的撤销/重做工作流 - 增加类型校验,避免传入无效类型
- 修正了原代码中的变量名错误(
sentences改为jars)
- 用
- 额外注意点:
- 所有Jar子类必须保持
[Serializable]标记 - 不要在Jar或其子类中引用非可序列化的类型(比如未标记
[Serializable]的自定义类),否则序列化仍会失败
- 所有Jar子类必须保持
内容的提问来源于stack exchange,提问作者Daniel Famakin
相关产品推荐
相关产品推荐

