找回密码
 立即注册
查看: 187|回复: 0

Unity:嵌套ScriptableObject的持久化存储

[复制链接]
发表于 2022-12-4 18:46 | 显示全部楼层 |阅读模式
假设我们有一个继承自 ScriptableObject 的子类:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace TestCode
{
    public class TestChildAsset : ScriptableObject
    {
        public List<string> testStrs;

        public TestChildAsset()
        {
            testStrs = new List<string>();
        }
    }
}
有一个继承自 ScriptableObject 的父类,其中包含子类的 List :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

namespace TestCode
{
    [CreateAssetMenu(fileName = "Assets/Test/Test.asset", menuName = "测试/新建一个父类")]
    public class TestParentAsset : ScriptableObject
    {
        public List<TestChildAsset> childs;

        public void AddChild(TestChildAsset child)
        {
            if(childs == null)
            {
                childs = new List<TestChildAsset>();
            }
            childs.Add(child);
        }
    }


    [CustomEditor(typeof(TestParentAsset))]
    public class TestParentAssetInspector : Editor
    {
        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();
            if (GUILayout.Button("Add New Child"))
            {
                TestParentAsset parent = this.target as TestParentAsset;
                TestChildAsset child = ScriptableObject.CreateInstance<TestChildAsset>();
                child.name = "TestChild";
                parent.AddChild(child);
            }
        }
    }
}

此时创建父类,添加新节点时会显示:


点击 TypeMissMatch 可以进入编辑,然而这个数据是无法存储下来的。触发代码编译或者 Unity 重启后这个数据都会丢失。
原因是 ScriptableObject 只能引用资产,引用了未被序列化的对象就会出现这个问题。因此结论是我们没有正确序列化子类,因为 CreateInstance 只是在内存中创建数据,并没有保存到磁盘里。
解决方案是把子类也都序列化保存下来:




只需要在父类里加一行修改就可以:
public void AddChild(TestChildAsset child)
{
    //调用 AddObjectToAsset 将子资源添加到父资源中
    AssetDatabase.AddObjectToAsset(child, this);
    if(childs == null)
    {
        childs = new List<TestChildAsset>();
    }
    childs.Add(child);
}用脚本执行上述过程:
string testPath = "Assets/Dango/ConfigInfo/Test.asset";
var parent = CreateInstance<TestParentAsset>();
var child = CreateInstance<TestChildAsset>();
var child2 = CreateInstance<TestChildAsset>();
child.name = "TestChild1";
child2.name = "TestChild2";
AssetDatabase.CreateAsset(parent, testPath);
parent.AddChild(child);
parent.AddChild(child2);
//更新数据
EditorUtility.SetDirty(parent);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
结果:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-6-2 07:26 , Processed in 0.098255 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表