【Unity】Property Drawerで独自の属性をもつメンバーの外観を変える

投稿者: | 2021-07-20

カスタムの属性を作って、その属性を持つメンバーのインスペクタでの見た目をProperty Drawerで変更してみました。

属性を作る

カスタムの属性はPropertyAttributeクラスを継承すると簡単に作れます。コンストラクタを使って、パブリックなメンバー変数に値を持たせることもできます。

using UnityEngine;

public class NaturalNumberAttribute : PropertyAttribute
{
    public readonly bool includeZero;

    public NaturalNumberAttribute(bool includeZero)
    {
        this.includeZero = includeZero;
    }
}

今回は、自然数を設定するための属性を作りました。0を含めるかどうかを示すbool型の値を引数に渡します。

フィールドに属性をつける

シーンにあるゲームオブジェクトにスクリプトを付けて、そのパブリックなフィールドに上の属性を付けました。

using UnityEngine;

public class TestScript1 : MonoBehaviour
{
    [NaturalNumber(true)] public int number;

    // Start is called before the first frame update
    void Start()
    {
        
    }

}

Property Drawerを作る

この属性のためのProperty Drawerを作ります。このスクリプトはEditorフォルダに置きました。

using UnityEngine;
using UnityEditor;

[CustomPropertyDrawer(typeof(NaturalNumberAttribute))]
public class NaturalNumberDrawer : PropertyDrawer
{
    
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        // 属性を取得
        NaturalNumberAttribute nn = (NaturalNumberAttribute)attribute;

        // 整数型のとき
        if (property.propertyType == SerializedPropertyType.Integer)
        {
            // 0を含めるとき
            if (nn.includeZero == true)
            {
                // 0以上ならそのまま表示
                if (property.intValue >= 0)
                {

                    EditorGUI.PropertyField(position, property);
                }
                // 0未満なら0にする
                else
                {

                    property.intValue = EditorGUI.IntField(position, 0);
                }

            }
            // 0を含めないとき
            else
            {
                // 1以上
                if (property.intValue >= 1)
                {
                    EditorGUI.PropertyField(position, property);
                }
                // 1未満
                else
                {
                    property.intValue = EditorGUI.IntField(position, 1);
                }
            }
        }
        
    }
}

このクラスにはCustomPropertyDrawer属性を付けて、PropertyDrawerクラスを継承させます。

[CustomPropertyDrawer(typeof(NaturalNumberAttribute))]
public class NaturalNumberDrawer : PropertyDrawer

OnGUIメソッドにインスペクタでの処理を書きます。

public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{

まず、プロパティの値が整数かどうかを確認して、そうでないときは何も表示しないようにしました。

整数のときは、属性が持つフィールドによって、0を含めるか含めないかを調べます。0を含めるときは値が0以上のときはそのまま表示して、0未満のときは0を表示し、値も0に設定します。

// 属性を取得
NaturalNumberAttribute nn = (NaturalNumberAttribute)attribute;

// 整数型のとき
if (property.propertyType == SerializedPropertyType.Integer)
{
    // 0を含めるとき
    if (nn.includeZero == true)
    {
        // 0以上ならそのまま表示
        if (property.intValue >= 0)
        {
            EditorGUI.PropertyField(position, property);
        }
        // 0未満なら0にする
        else
        {
            property.intValue = EditorGUI.IntField(position, 0);
        }

    }

0を含めないときは1以上かどうかを調べて同様の操作をします。

// 0を含めないとき
else
{
    // 1以上
    if (property.intValue >= 1)
    {
        EditorGUI.PropertyField(position, property);
    }
    // 1未満
    else
    {
        property.intValue = EditorGUI.IntField(position, 1);
    }
}

これで自然数だけを設定できるようになりました。

コメントを残す

メールアドレスが公開されることはありません。