memomem

備忘録・メモ置き場

PropertyDrawer にハマった

古い情報が多くてハマってしまった。

var enableProperty = property.FindPropertyRelative("enable");
enableProperty.boolValue = EditorGUI.Toggle(drawRect, "enable", enableProperty.boolValue);

みたいな書き方があるが、これだとインスペクターを複数選択したときに、勝手に値が変更されてしまう。 これよりも

EditorGUI.PropertyField(drawRect, property.FindPropertyRelative("enable"), new GUIContent("enable"), false);

の方がシンプルでどのtypeでも共通で使える為簡単。

また、要素が重なったりするときは、

public override float GetPropertyHeight(SerializedProperty property, GUIContent label)

の中などで記載していく必要がある。

雛形

[CustomPropertyDrawer(typeof(TweenAnimChildren))]
public class TweenAnimChildrenDrawer : PropertyDrawer
{
    Color playingColor = Color.green;

    public override void OnGUI(Rect drawRect, SerializedProperty property, GUIContent label)
    {
        EditorGUI.BeginProperty(drawRect, label, property);
        //
        var isPlayingChainsProperty = property.FindPropertyRelative("isPlayingChains");
        var isPlayingParallelsProperty = property.FindPropertyRelative("isPlayingParallels");

        GUI.contentColor = isPlayingChainsProperty.boolValue ? playingColor : Color.white;
        drawRect.y += EditorGUIUtility.singleLineHeight + 2f;
        EditorGUI.PropertyField(drawRect, property.FindPropertyRelative("chains"), new GUIContent("chains"), true);

        float childGroupH = EditorGUI.GetPropertyHeight(property.FindPropertyRelative("chains"), true);
        drawRect.y += childGroupH;

        GUI.contentColor = isPlayingParallelsProperty.boolValue ? playingColor : Color.white;
        drawRect.y += EditorGUIUtility.singleLineHeight + 2f;
        EditorGUI.PropertyField(drawRect, property.FindPropertyRelative("parallels"), new GUIContent("parallels"), true);
        //
        GUI.contentColor = Color.white;
        EditorGUI.EndProperty();
    }

    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        var padding = 5;
        var lineH = EditorGUIUtility.singleLineHeight + 4;
        var height = 0f;

        var chainsGroupProperty = property.FindPropertyRelative("chains");
        var parallelsGroupProperty = property.FindPropertyRelative("parallels");

        float childGroupH = EditorGUI.GetPropertyHeight(chainsGroupProperty, true);
        float parallelsGroupH = EditorGUI.GetPropertyHeight(parallelsGroupProperty, true);
        height += childGroupH + parallelsGroupH + padding;

        height += lineH * 1.5f;
        return height + padding;
    }
}

下記のUnity公式がわかりやすい。

using UnityEditor;
using UnityEngine;

// IngredientDrawer
[CustomPropertyDrawer(typeof(Ingredient))]
public class IngredientDrawer : PropertyDrawer
{
    // 指定された矩形内のプロパティーを描画
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        // 親プロパティーで BeginProperty / EndProperty を使用することは、    
    // プレハブオーバーライドロジックがプロパティー全体で機能することを意味します。
        EditorGUI.BeginProperty(position, label, property);

        // ラベルを描画
        position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);

        // 子のフィールドをインデントしない 
        var indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;

        // 矩形を計算
        var amountRect = new Rect(position.x, position.y, 30, position.height);
        var unitRect = new Rect(position.x + 35, position.y, 50, position.height);
        var nameRect = new Rect(position.x + 90, position.y, position.width - 90, position.height);

        // フィールドを描画 - GUIContent.none をそれぞれに渡すと、ラベルなしに描画されます
        EditorGUI.PropertyField(amountRect, property.FindPropertyRelative("amount"), GUIContent.none);
        EditorGUI.PropertyField(unitRect, property.FindPropertyRelative("unit"), GUIContent.none);
        EditorGUI.PropertyField(nameRect, property.FindPropertyRelative("name"), GUIContent.none);

        // インデントを元通りに戻します
        EditorGUI.indentLevel = indent;

        EditorGUI.EndProperty();
    }
}

docs.unity3d.com

参考

light11.hatenadiary.com

qiita.com

www.tangledrealitystudios.com