Unity 枚举选择编辑器窗口

功能

  • 将枚举值通过按钮列表展示出来
  • 可以通过搜索框搜索筛选枚举值
  • 示例图如下在这里插入图片描述

作用范围

  • 单枚举属性
[Header("掉落音效"), EnumPicker] public GameAudioType colAudioType;
  • 枚举数值属性(暂不支持列表List属性)
 [Header("其他掉落音效"), EnumPicker] public GameAudioType[] colAudioTypes;

编辑器源码

  • 脚本文件结构如下图
    文件结构

  • EnumPickerDrawer

using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;

namespace CFM.Attribute
{
    // 属性绘制器要指定要绘制的属性类型
    [CustomPropertyDrawer(typeof(EnumPickerAttribute))]
    public class EnumPickerDrawer : PropertyDrawer
    {
        // 重写属性的UI呈现方式
        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            // 只处理枚举类型的属性
            if (property.propertyType == SerializedPropertyType.Enum)
            {
                EditorGUI.BeginProperty(position, label, property);
                CreateEnumButton(position, property);
                EditorGUI.EndProperty();
            }
        }

        FieldInfo GetFieldInfoFromPath(Type classType, string path)
        {
            FieldInfo fieldInfo = null;
            string[] parts = path.Split('.');

            foreach (var part in parts)
            {
                if (part == "Array")
                {
                    // Skip artificial "Array" part of path
                    continue;
                }

                if (part.StartsWith("data["))
                {
                    // We've found the array index part, so we stop here
                    break;
                }

                // Regular field
                fieldInfo = classType.GetField(part,
                    BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance |
                    BindingFlags.FlattenHierarchy);
                if (fieldInfo == null)
                    return null; // or throw some exception
            }

            return fieldInfo;
        }

        private FieldInfo fieldInfo;
        private Type actualEnumType;

        void CreateEnumButton(Rect position, SerializedProperty property)
        {
            try
            {
                if (GUI.Button(position, property.enumDisplayNames[property.enumValueIndex]))
                {
                    var classType = property.serializedObject.targetObject.GetType();
                    var propertyPath = property.propertyPath;
//                Debug.LogError(
//                    $"属性类型:{property.propertyType},获取的{property.enumDisplayNames[property.enumValueIndex]}属性是否是数组:{property.isArray},属性路径:{propertyPath}");
                    fieldInfo = null;
                    bool isArray = propertyPath.Contains("Array");
                    if (isArray)
                        fieldInfo = GetFieldInfoFromPath(classType, propertyPath);
                    else
                        fieldInfo = classType.GetField(property.name,
                            BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

                    if (fieldInfo != null)
                    {
                        if (isArray)
                            actualEnumType = fieldInfo.FieldType.GetElementType();
                        else
                            actualEnumType = fieldInfo.FieldType;
                        // 打开一个选择窗口,并且当选择枚举值后,更新属性的值
                        EnumPickerWindow.Init(actualEnumType, property.enumNames, selectedIndex =>
                        {
                            // 设置选择的枚举值
                            property.enumValueIndex = selectedIndex;
                            property.serializedObject.ApplyModifiedProperties(); // 应用属性修改
                        });
                    }
                }
            }
            catch (Exception e)
            {
                // 设置选择的枚举值
                property.enumValueIndex = 0;
                property.serializedObject.ApplyModifiedProperties(); // 应用属性修改
            }
        }
    }
}
  • EnumPickerWindow
using System;
using UnityEditor;
using UnityEngine;

namespace CFM.Attribute
{
    public class EnumPickerWindow : EditorWindow
    {
        EnumPickerWindow()
        {
            this.titleContent = new GUIContent("枚举选择");
        }


        private string _searchText = "";
        private Vector2 _scrollPosition;
        private System.Type _enumType;
        private string[] _enumNames;
        private int _selectedValue;

        // 打开窗口的方法
        public static void Init<TEnum>(System.Action<TEnum> onPicked) where TEnum : System.Enum
        {
            // 创建窗口
            EnumPickerWindow window = GetWindow<EnumPickerWindow>(true, "枚举选择", true);
            window._enumType = typeof(TEnum);
            window._enumNames = System.Enum.GetNames(typeof(TEnum));
            window._selectedValue = 0;
            window.Show();

            // 注册选择回调
            window._onPicked = obj => onPicked((TEnum) obj);
        }
        
        public static void Init(Type type, string[] enumNames, System.Action<int> onPicked)
        {
//            Debug.LogError($"打印枚举类型:{type.Name}");
            EnumPickerWindow window = GetWindow<EnumPickerWindow>(true, "枚举选择", true);
            window._enumType = type;
            window._enumNames = enumNames;
            window._selectedValue = 0;
            window.Show();

            // 注册选择回调
            window._onPicked_int = onPicked; // 这里存储的回调只需要一个int型的selectedIndex
        }

        // 在这里添加枚举选择的回调
        private System.Action<System.Enum> _onPicked;
        private System.Action<int> _onPicked_int;

        void OnGUI()
        {
            // 搜索框
            _searchText = EditorGUILayout.TextField("Search", _searchText);

            // 枚举列表滚动视图
            _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition);

            foreach (var name in _enumNames)
            {
                // 如果搜索框不为空且枚举名称不包含搜索文本,跳过此枚举值
                if (!string.IsNullOrEmpty(_searchText) && !name.ToLower().Contains(_searchText.ToLower()))
                    continue;

                if (GUILayout.Button(name))
                {
                    // 当点击了某个枚举值时
                    var enumVal = System.Enum.Parse(_enumType, name) as System.Enum;
                    _selectedValue = Convert.ToInt32(enumVal);
                    var selectIndex = Array.IndexOf(_enumNames, name);
//                    Debug.LogError($"选择枚举值:{enumVal}:{_selectedValue},枚举索引:{selectIndex}");
                    _onPicked?.Invoke(enumVal);
                    _onPicked_int?.Invoke(selectIndex);
                    Close(); // 关闭窗口
                }
            }

            EditorGUILayout.EndScrollView();
        }
    }
}
  • EnumPickerAttribute
using System;
using UnityEngine;

namespace CFM.Attribute
{
    [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
    public class EnumPickerAttribute : PropertyAttribute
    {
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值