美文网首页
Odin Inspector 系列教程 --- 初识Odin序列

Odin Inspector 系列教程 --- 初识Odin序列

作者: su9257_海澜 | 来源:发表于2019-12-02 19:20 被阅读0次

    前言,在Unity开发中,一些挂在物体上的脚本公开的成员变量,可通过inspector面板更改对应的值,但并不是所有公开成员的值,都可以通过inspector面板进行填写,而且有些数值即使填写,也保存不了(无法序列化),例如:Dictionary<Tkey,TValue>。但是Odin为我们提供了一套解决这种情况的序列化方案。

    如下图所示,keyValuePairs_0成员和keyValuePairs_1成员都无法进行有效的序列化,虽然keyValuePairs_1通过特性ShowInInspector强制显示出对应的Dictionary,也可以填写,但是在运行时,填写的数据会丢失。

    public class ExampleUnitySerializedScript : MonoBehaviour
    {
        public Dictionary<int, string> keyValuePairs_0 = new Dictionary<int, string>();
    
        [ShowInInspector]
        public Dictionary<int, string> keyValuePairs_1 = new Dictionary<int, string>();
    }
    

    使用Odin序列化

    使用比较简单,默认情况下我们继承的是 MonoBehaviour,现在我们只需要用SerializedMonoBehaviour代替MonoBehaviour即可,即开即用,非常简单。

    public class ExampleUnitySerializedScript : SerializedMonoBehaviour
    {
        public Dictionary<int, string> keyValuePairs_0 = new Dictionary<int, string>();
    
        [ShowInInspector]
        public Dictionary<int, string> keyValuePairs_1 = new Dictionary<int, string>();
    }
    

    对应SerializedMonoBehaviour这类Odin序列化类,总共有以下7种,足以满足日常开发中的绝大多数需求

    • SerializedMonoBehaviour
    • SerializedBehaviour
    • SerializedComponent
    • SerializedNetworkBehaviour
    • SerializedScriptableObject
    • SerializedStateMachineBehaviour
    • SerializedUnityObject

    这时有同学会问,Odin序列化是不是强制替换了原有的Unity序列化?有什么需要注意的地方呢?

    第一个问题:Odin序列化默认情况是不会替换Unity原有序列化的,Odin序列化仅仅是基于Unity序列化的扩展,对成员进行序列化时,如果Unity支持,就使用Unity序列化,如果不支持,转由Odin序列化接手。

    第二个问题:注意事项是有的,就像刚刚的回答,默认的情况下Odin不会替换Unity原有支持的序列化情况,但是我们可以强制使用Odin序列化,或者强制让Unity序列化和Odin序列化并存,当然这种并存也会出现2份数据,所以不建议这么做。如果对这段解答不是很理解,请看下面的示例

    示例到代码

    using Sirenix.OdinInspector;
    using Sirenix.Serialization;
    using System;
    using System.Collections.Generic;
    using UnityEngine;
    
    
    public class ExampleOdinSerializedScript : SerializedMonoBehaviour
    {
        // 使用Odin序列化,而非Unity序列化
        public Dictionary<int, string> firstDictionary= new Dictionary<int, string>();
    
        // MyClassByUnity 因为标记为 Serializable ,所以使用Unity 自带的序列化,而非Odin 序列化
        public MyClassByUnity myUnityReference = new MyClassByUnity();
    
        //强制使用 Odin 序列化,而不使用Unity的序列化
        [NonSerialized, OdinSerialize]
        public MyClassByOdin myOdinReference = new MyClassByOdin();
    
        private void Start()
        {
            Debug.Log(firstDictionary.Count);
            Debug.Log(myUnityReference.secondDictionary_Unity.Count);
            Debug.Log(myOdinReference.secondDictionary_Odin.Count);
        }
        
    }
    
    [Serializable]
    public class MyClassByUnity
    {
        // 虽然标记为 OdinSerialize 特性, 但是依然不会被序列化
        [OdinSerialize]
        public Dictionary<int, string> secondDictionary_Unity = new Dictionary<int, string>();
    }
    
    [Serializable]
    public class MyClassByOdin
    {
        [OdinSerialize]
        [NonSerialized]
        public Dictionary<int, string> secondDictionary_Odin= new Dictionary<int, string>();
    }
    

    成员变量firstDictionary是Unity不支持的Dictionary类型,所以默认使用Oidn 序列化,如果强行标记Serializable特性会出现如下报错

    成员变量MyUnityReference是MyClassByUnity类型,在MyClassByUnity类中对应的成员SecondDictionary_Unity标记特性OdinSerialize,按常理secondDictionary_Unity字段会使用Odin序列化,但是MyClassByUnity类标记了Serializable特性,所以MyClassByUnity会按照Unity序列化的方式,又因为MyClassByUnity为Unity序列化不支持的类,所以直接跳过。类似一个for循环中,在索引0处执行break,后面的数据不会遍历一样(此处感觉略微啰嗦)。

    为了避免上面的情况发生,我们使用[NonSerialized, OdinSerialize]两个特性,这是告诉编辑器,拒绝使用Unity原有的序列化,而是强制使用Odin自带的序列化系统,这样,上面的问题就可迎刃而解。

    Odin是一个强大的系统,在后面的章节中笔者会更详细的介绍Odin的序列化系统,如果你感觉Odin不错,就把他推荐给你的同伴吧


    更多教程内容详见:革命性Unity 编辑器扩展工具 --- Odin Inspector 系列教程

    相关文章

      网友评论

          本文标题:Odin Inspector 系列教程 --- 初识Odin序列

          本文链接:https://www.haomeiwen.com/subject/zsvfgctx.html