基于Odin插件简单ScriptableObject数据管理类

Posted rk_21125

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于Odin插件简单ScriptableObject数据管理类相关的知识,希望对你有一定的参考价值。

前言 : 该类基于官方视屏略微修改的基类,通过继承即可实现指定数据管理

using Sirenix.OdinInspector;
using Sirenix.OdinInspector.Editor;
using Sirenix.Utilities.Editor;
using System;
using UnityEditor;
using UnityEngine;

namespace EditorModules

    public class BaseDataEditor<T> : OdinMenuEditorWindow where T : ScriptableObject
    
        protected Type dataType;
        protected string path;

        private CreateNewData<T> newData;

        protected override void OnDestroy()
        
            base.OnDestroy();
            if (newData != null)
                DestroyImmediate(newData.data);
        

        /// <summary>
        /// 提供子类初始化数据使用
        /// </summary>
        /// <param name="dataType"></param>
        /// <param name="path"></param>
        protected void InitData(Type dataType, string path)
        
            this.dataType = dataType;
            this.path = path;
        

        protected override OdinMenuTree BuildMenuTree()
        
            CreateNewData<T> newData = new CreateNewData<T>(path);

            //构建菜单
            var tree = new OdinMenuTree();
            tree.Config.DrawSearchToolbar = true;//开启搜索状态
            tree.Add("Creat New Data", newData);
            tree.AddAllAssetsAtPath(dataType.Name, "Assets/Game Data/", dataType, true, true);
            tree.Selection.SelectionConfirmed += x => EditorGUIUtility.PingObject(x.SelectedValue as T);//双击跳转选择对象的目录
            return tree;
        

        protected override void OnBeginDrawEditors()
        
            //gets reference to currently selected item
            OdinMenuTreeSelection selected = this.MenuTree.Selection;
            SirenixEditorGUI.BeginHorizontalToolbar();
            
                T asset = selected.SelectedValue as T;
                string path = AssetDatabase.GetAssetPath(asset);

                GUILayout.FlexibleSpace();

                if (SirenixEditorGUI.ToolbarButton("Ping"))
                
                    EditorGUIUtility.PingObject(asset);
                
                else if (SirenixEditorGUI.ToolbarButton("Show In Explorer"))
                
                    EditorUtility.RevealInFinder(path);
                
                else if (SirenixEditorGUI.ToolbarButton("Delete Current"))
                
                    AssetDatabase.DeleteAsset(path);
                    AssetDatabase.SaveAssets();
                
            
            SirenixEditorGUI.EndHorizontalToolbar();
        
    

    public class CreateNewData<T> where T : ScriptableObject
    
        [InlineEditor(ObjectFieldMode = InlineEditorObjectFieldModes.Hidden)]
        public T data;
        private string path;

        public CreateNewData(string path)
        
            data = ScriptableObject.CreateInstance<T>();
            this.path = path;
        

        [Button("Add New Data", ButtonSizes.Large, ButtonStyle.FoldoutButton)]
        private void CreateData(string dataName)
        
            AssetDatabase.CreateAsset(data, "Assets/" + path + "/" + dataName + ".asset");
            AssetDatabase.SaveAssets();

            //create new instance of SO
            data = ScriptableObject.CreateInstance<T>();
        
    

 

使用例子:

using UnityEditor;

namespace EditorModules

    public class ActionDataEditor : BaseDataEditor<ActionData>
    
        [MenuItem("Tools/Data Editor/Action Data")]
        public static void ShowEditor() => GetWindow<ActionDataEditor>();

        protected override void OnEnable()
        
            base.OnEnable();
            InitData(typeof(ActionData), "Game Data/ActionData");
        
    

(其中,Game Data/ActionData 为创建的ScriptableObject在Assets的路径)

 

实现效果

Unity3D Odin Inspector 简单介绍与入门

环境:Unity2021.1.14 Odin3.0.4 语言:C#

面向:Editor开发人员

总起

从很早之前粗略了解Odin,看到它炫酷地Editor实现方式,到现在重度使用,慢慢的一个疑问缠绕在我心中。

Odin究竟解决了一个什么问题?

根据半年的使用经验,我尝试回答一下这个问题。

Odin提供一整套Editor UI绘制的解决方案,大概有四个特点:

  1. 以数据类作为核心绘制单元,通过打Attribute形式指定绘制形式;
  2. 100多个Attribute提供了庞大的绘制能力与参考代码;
  3. 极大拓展了Unity基础绘制能力,如多态、字典;
  4. 通过Processor、ValueDrawer等机制可以灵活应对各种需求;

这使得仅仅通过简单的代码就能创建复杂多变的Editor。它或许并不能脱离IMGUI本身的限制,但它能使得开发轻松而高效。

一个例子

Unity自身实现一个按钮的方式:

using UnityEditor;
using UnityEngine;

public class TestOdinIntro2 : MonoBehaviour



[CustomEditor(typeof(TestOdinIntro2))]
public class TestOdinIntro2Editor : Editor

    public override void OnInspectorGUI()
    
        base.OnInspectorGUI();

        if (GUILayout.Button("Click"))
        
            Debug.LogError("Hello world2");
        
    

使用Odin实现一个按钮:

using Sirenix.OdinInspector;
using UnityEngine;

public class TestOdinIntro : MonoBehaviour

    [Button]
    public void Click()
    
        Debug.LogError("Hello world");
    

效果:

Odin本质还是使用IMGUI,但它使用Attribute的方式使得绘制界面更容易组织、更容易应对游戏实际开发过程中多变的需求。

更加别提Odin极大扩展了Unity的绘制,诸如多态、字典。如果对UnityEditor有重度需求,Odin是个强烈推荐的插件。

学习资料

本节介绍一下我在实践过程中是如何学习Odin的。

首先推荐的是Odin各种Attribute的例子,一开始可以根据需求去找现有的Attribute:

 

安装插件后可以在Unity菜单栏Tools/Odin Inspector/Attribute Overview找到或者官网https://odininspector.com/attributes上也可预览。

Odin的进阶用法

 

可以在插件的Serenix/Demos目录下找到。

这里包括自定义Drawer和Processor等Odin的进阶用法,这类功能开始切入Odin的本质,是想要灵活应用Odin必备的知识。

官网的tourial

 

网址:https://odininspector.com/tutorials

里面针对Odin各类主题,如Attribute、Custom Editor、Serialize等有详细的说明。一开始可以大致浏览一遍,后续可以根据需求具体研究。

顺便推荐一下UnityEditor相关的有个十分经典的教程:http://49.233.81.186/

最后两个实用小工具:Serialization DebuggerStatic Inspector

 

 

分别可以在Unity菜单栏中找到:

1.Tools/Odin Inspector/Serialization Debugger

2.Tools/Odin Inspector/Static Inspector

Serialization Debugger是查看序列化问题非常好用的工具,遇到诸如“为什么没使用Odin绘制出来?”等问题就可以使用。

而Static Inspector是检查静态数据的工具。

以上是关于基于Odin插件简单ScriptableObject数据管理类的主要内容,如果未能解决你的问题,请参考以下文章

基于Odin的常见小工具ScriptableObjectCreator存在ToHashSet二义性时的解决方案

Unity3D Odin Inspector 简单介绍与入门

Unity3D Odin Inspector 简单介绍与入门

很好用的Unity编辑器扩展工具 Odin Inspector教程

Unity3D Editor Undo回退效果实现3 Odin相关

Unity3D Editor Undo回退效果实现3 Odin相关