Unity:嵌套ScriptableObject的持久化存储
假设我们有一个继承自 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
{
public class TestParentAsset : ScriptableObject
{
public List<TestChildAsset> childs;
public void AddChild(TestChildAsset child)
{
if(childs == null)
{
childs = new List<TestChildAsset>();
}
childs.Add(child);
}
}
public class TestParentAssetInspector : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (GUILayout.Button(&#34;Add New Child&#34;))
{
TestParentAsset parent = this.target as TestParentAsset;
TestChildAsset child = ScriptableObject.CreateInstance<TestChildAsset>();
child.name = &#34;TestChild&#34;;
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 = &#34;Assets/Dango/ConfigInfo/Test.asset&#34;;
var parent = CreateInstance<TestParentAsset>();
var child = CreateInstance<TestChildAsset>();
var child2 = CreateInstance<TestChildAsset>();
child.name = &#34;TestChild1&#34;;
child2.name = &#34;TestChild2&#34;;
AssetDatabase.CreateAsset(parent, testPath);
parent.AddChild(child);
parent.AddChild(child2);
//更新数据
EditorUtility.SetDirty(parent);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
结果:
页:
[1]