基于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的路径)

 

实现效果

posted @ 2023-04-07 02:33  rkmao  阅读(529)  评论(0编辑  收藏  举报