zoukankan      html  css  js  c++  java
  • Unity开发笔记-使用AssetDatabase.AddObjectToAsset函数,正确序列化ScriptableObject的多态数组,修复TypeMissMatch错误

    假设我们需要使用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中了

  • 相关阅读:
    十大Intellij IDEA快捷键
    IDEA 在同一目录创建多个项目
    IDEA2017 使用(二)
    idea使用(一)
    js == 与 === 的区别[转]
    Spring Boot(一)
    微服务实战(一):微服务架构的优势与不足
    phpcms:三、头部包含
    phpcms:二、头部尾部包含
    phpcms:一、安装及新建模板
  • 原文地址:https://www.cnblogs.com/terrynoya/p/14417952.html
Copyright © 2011-2022 走看看