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

Posted rk_21125

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于Odin的常见小工具ScriptableObjectCreator存在ToHashSet二义性时的解决方案相关的知识,希望对你有一定的参考价值。

注:提供给对链式调用不熟悉的人的解决方案

网上随处可见的基于Odin的小工具ScriptableObjectCreator如果发生【以下方法或属性之间的调用具有二义性:“Sirenix.Utilities.LinqExtensions.ToHashSet<T>(System.Collections.Generic.IEnumerable<T>)”和“System.Linq.Enumerable.ToHashSet<TSource>(System.Collections.Generic.IEnumerable<TSource>”】

static HashSet<Type> scriptableObjectTypes = AssemblyUtilities.GetTypes(AssemblyTypeFlags.CustomTypes)
        .Where(t => t.IsClass &&
            typeof(ScriptableObject).IsAssignableFrom(t) &&
            !typeof(EditorWindow).IsAssignableFrom(t) &&
            !typeof(Editor).IsAssignableFrom(t)).ToHashSet();

把ToHashSet提出来,限定调用

static HashSet<Type> scriptableObjectTypes = System.Linq.Enumerable.ToHashSet(AssemblyUtilities.GetTypes(AssemblyTypeFlags.CustomTypes)
        .Where(t => t.IsClass &&
            typeof(ScriptableObject).IsAssignableFrom(t) &&
            !typeof(EditorWindow).IsAssignableFrom(t) &&
            !typeof(Editor).IsAssignableFrom(t)));

 

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

 

实现效果

以上是关于基于Odin的常见小工具ScriptableObjectCreator存在ToHashSet二义性时的解决方案的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

小程序商城工具平台测评

小程序商城工具平台测评

Unity3D Odin Inspector 简单介绍与入门