假设我们需要使用ScriptableObject来保存一个图的结构,我们先创建2个ScriptableObject的子类,Graph和GraphNodeBase
GraphNodeBase类如下
namespace YaoJZ.SerializeTest
{
public class GraphNodeBase:ScriptableObject
{
}
}
Graph类如下
namespace YaoJZ.SerializeTest
{
[CreateAssetMenu(fileName = "graph.asset",menuName = "yaojz/graph")]
public class Graph:ScriptableObject
{
public List<GraphNodeBase> Nodes;
public void AddNode(GraphNodeBase node)
{
Nodes.Add(node);
}
}
}
我们需要根据需求扩展GraphNodeBase的子类,比如AnimationClipNode
namespace YaoJZ.SerializeTest
{
public class AnimationClipNode:GraphNodeBase
{
public AnimationClip Clip;
}
}
我们需要CreateAssetMenu用来创建Graph.asset资产
现在我们需要扩展一下Graph的Inspector,增加一个按钮,用来添加节点,用来添加AnimationClipNode
namespace YaoJZ.SerializeTest.Editor
{
[CustomEditor(typeof(Graph))]
public class GraphInspector:UnityEditor.Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (GUILayout.Button("add animation node"))
{
Graph g = this.target as Graph;
g.AddNode(ScriptableObject.CreateInstance<AnimationClipNode>());
}
}
}
}
现在我们点击一下按钮
出现了TypeMissMatch,这显然不是我们想要的AnimationClipNode,原因是ScriptableObject只能引用资产,引用了未被序列化的对象就会出现这个问题。因此结论是我们没有正确序列化AnimationClipNode,因为CreateInstance只是创建再内存中,并没有保存到磁盘里。
解决方案很简单,只需要AssetDatabase.AddObjectToAsset,将AnimationClipNode嵌入到已被序列化好的Graph中即可
更新后的Graph类
public class Graph:ScriptableObject
{
public List<GraphNodeBase> Nodes;
public void AddNode(GraphNodeBase node)
{
AssetDatabase.AddObjectToAsset(node,this); //将node序列化,并嵌入graph对象中
if (Nodes == null)
{
Nodes = new List<GraphNodeBase>();
}
Nodes.Add(node);
}
}
按一下ctrl+s保存下项目,查看graph.asset,就可以发现node已作为孩子节点被序列化在graph中了