为何第二次程序集重载后我的Scriptable Object数据全部丢失?
问题分析与解决方案
核心问题根源
你遇到的数据丢失问题,本质是Scriptable Object(SO)的使用方式错误:
- 多余的
[System.Serializable]标签:ScriptableObject本身继承自UnityEngine.Object,已经内置Unity序列化支持,额外添加该标签会干扰正常序列化逻辑。 - 错误设置
hideFlags:作为磁盘Asset存在的SO,Unity会自动管理其生命周期,强制设置DontUnloadUnusedAsset会破坏资源加载/卸载流程,反而导致状态异常。 - 未将
SpellComponent保存为独立Asset:如果在Spell的Inspector中直接添加临时创建的SpellComponent实例(而非已保存的Asset),程序集重载(如二次进入PlayMode)时临时对象会被销毁,数据自然丢失。 - 代码拼写错误:
Spell类中的virutal应为virtual,编译异常会间接影响序列化稳定性。
修正后的代码示例
Spell类
[CreateAssetMenu(menuName = "Spell", fileName = "New Spell")] public class Spell : ScriptableObject { [SerializeField] private List<SpellComponent> m_Components; public virtual void OnEnable() { // 移除hideFlags设置,交由Unity默认管理资源生命周期 } }
SpellComponent类
[CreateAssetMenu(menuName = "Spell Component", fileName = "New Spell Component")] public abstract class SpellComponent : ScriptableObject { [SerializeField] int m_ExampleInt; public virtual void OnEnable() { // 移除hideFlags设置 } }
正确操作流程
- 先通过
CreateAssetMenu创建独立的SpellComponentAsset(比如火焰组件、冰冻组件),编辑m_ExampleInt后保存到磁盘。 - 创建
SpellAsset,在Inspector中将已保存的SpellComponentAsset拖拽到m_Components列表中。 - 此时无论多少次进入PlayMode或触发程序集重载,数据都会正常保留。
补充说明
如果需要动态生成临时的SpellComponent实例(无需持久化到磁盘),可以使用ScriptableObject.CreateInstance<具体子类>(),但这类实例的数据不会被保存,程序重启或重载后会自动丢失,仅适用于 runtime 临时逻辑。
内容的提问来源于stack exchange,提问作者Kube
相关产品推荐
相关产品推荐

