Unity Inspector에서 Enum의 일부 항목을 숨기는 방법

13218 단어 C#Unity

하고 싶은 일



직렬화된 EnumField의 내용을 변경하지 않고 Editor에서 표시할 수 있는 항목을 제한하고 싶습니다.
// サンプルEnumの定義
public enum ColorEnum {
    None = 0,
    Red = 1,
    Green = 2,
    Blue = 3
}

그대로 Editor로 표시시킬 경우 모든 항목을 선택 가능
[SerializeField] ColorEnum myColor;



이와 같이, 「HideEnumItem」이라고 하는 마법 Attribute를 붙이는 것으로, Editor로 표시된 「myColor」로부터 「None」과 「Red」를 숨기고 싶다
[HideEnumItem("None", "Red"), SerializeField] ColorEnum myColor;



「HideEnumItem」이라는 마법 Attribute는 아래와 같은 「Custom Attribute」와 「Custom Property Drawer」로 준비한다.

Custom Attribute 준비



"Custom Attribute"은 c# 표준 기능으로, "SerializeField"와 같은 Attribute를 자작할 수 있습니다.

먼저 일반 Scripts 폴더에서 아래의 "HideEnumItemAttribute.cs"파일을 만듭니다.
using System.Collections.Generic;
using UnityEngine;

// AttributeUsageで使用できる変数をクラスのフィールドに限定
[System.AttributeUsage(System.AttributeTargets.Field)]
public class HideEnumItemAttribute : PropertyAttribute
{
    // 隠したい項目を保存用
    public HashSet<string> Filter { get; private set; }
    public HideEnumItemAttribute(params string[] filters)
    {
        Filter = new HashSet<string>();
        for (var i = 0; i < filters.Length; i++) {
            Filter.Add(filters[i]);
        }
    }
}

Custom Property Drawer 준비



Custom Property Drawer 」는 UnityEditor의 기능으로, Editor의 인스펙터 주위의 묘화를 커스터마이즈 할 수가 있습니다.

위의 HideEnumItemAttribute를 받고 지정된 항목을 숨기는 "HideEnumItemAttribute.cs"파일을 만듭니다 (이것은 UnityEditor의 API를 사용하므로 Editor 폴더에 넣어야합니다) :
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;

// 自作のAttributeを指定
[CustomPropertyDrawer(typeof(HideEnumItemAttribute))]
public class HideEnumItemDrawer : PropertyDrawer
{
    int selectedIndex;
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        // Attribute取得
        var filterInfo = (HideEnumItemAttribute)attribute;
        // eunmValueIndex変換用
        var enum2index = new Dictionary<int, int>(property.enumNames.Length);
        for (int i = 0; i < property.enumNames.Length; i++)
        {
            var enumEntry = Enum.Parse(fieldInfo.FieldType, property.enumNames[i]);
            enum2index[(int)enumEntry] = i;
        }
        // 表示項目を加工
        var filteredItems = property.enumNames.Where(item => !filterInfo.Filter.Contains(item)).ToList();
        // Editor表示の同期
        selectedIndex = filteredItems.IndexOf(property.enumNames[property.enumValueIndex]);
        // シリアライズされた値が範囲外だった場合、最初の項目に設定
        if (selectedIndex < 0) {
            selectedIndex = 0;
            var mappedEnum = Enum.Parse(fieldInfo.FieldType, filteredItems[selectedIndex]);
            property.enumValueIndex = enum2index[(int)mappedEnum];
        }

        // オリジナルの代わりに、加工されたリストを描画
        using (var check = new EditorGUI.ChangeCheckScope())
        {
            selectedIndex = EditorGUI.Popup(position, label.text, selectedIndex, filteredItems.ToArray());
            if (check.changed)
            {
                // 元のEnum値に変換
                var mappedEnum = Enum.Parse(fieldInfo.FieldType, filteredItems[selectedIndex]);
                property.enumValueIndex = enum2index[(int)mappedEnum];
            }
        }
    }
}

요약



이와 같이 「Custom Attribute」와 「Custom Property Drawer」를 조합하는 것으로, 범용적이고 효율적인 Editor 확장을 할 수 있게 되므로, 편리하게 하고 싶네요. 덧붙여서, 이러한 편리한 「Custom Attribute」를 많이 준비해 주는 Unity 에셋이 「Odin Inspector And Serializer」이 됩니다. 흥미있는 분은 꼭 체크해 보세요.

좋은 웹페이지 즐겨찾기