功能
- 将枚举值通过按钮列表展示出来
- 可以通过搜索框搜索筛选枚举值
- 示例图如下
作用范围
- 单枚举属性
[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
{
}
}