【Unity】【エディタ拡張】複数のEnumを一つのポップアップで表示するPropertyAttribute

複数のEnumをあたかも一つのEnumのPropertyFieldのように扱えるPropertyAttributeです。

ソースコード

PropertyAttributeとそのDrawerを次のように書きます。

using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

[System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple = false)]
public class EnumPopupAttribute : PropertyAttribute
{
    public string[] Names { get; private set; }
    public int[] Values { get; private set; }

    public EnumPopupAttribute(params System.Type[] types)
    {
        var names       = new List<string>();
        var values      = new List<int>();
        foreach (var type in types) {
        
            var currentNames    = System.Enum.GetNames(type);
            var currentValues   = System.Enum.GetValues(type);
            for (int i = 0; i < currentNames.Length; i++) {
                var currentName     = currentNames[i];
                var currentValue    = (int)currentValues.GetValue(i);
                if (names.Contains(currentName) || values.Contains(currentValue)) {
                    // 名前か値がかぶっている場合は例外
                    throw new System.Exception("Invalid : " + type.FullName + "." + currentName);
                }
                else {
                    names.Add(currentName);
                    values.Add(currentValue);
                }
            }
        }
        Names           = names.ToArray();
        Values          = values.ToArray();
    }
}

#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(EnumPopupAttribute))]
public class EnumPopupAttributeDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        var attr    = attribute as EnumPopupAttribute;
        property.intValue   = EditorGUI.IntPopup(position, property.displayName, property.intValue, attr.Names, attr.Values);
    }
}
#endif

単純に二つのenumをIntPopupを用いて表示しているだけです。
今回はenum要素の値や名前が被るとエラーになるようにしています。

結果

使う側のソースコードは次のように書きます。

using UnityEngine;

public enum Base
{
    One     = 1,
    Two     = 2,
    Three   = 3,
}

public enum Additional
{
    Four    = 4,
    Five    = 5,
}
public class EnumPopupAttributeExample : MonoBehaviour {

    [EnumPopup(typeof(Base), typeof(Additional))]
    public int _sample;
}

結果は下図のようになります。

f:id:halya_11:20180820161211p:plain

二つのEnumを一つのEnumであるかのように表示できました。