うにてぃブログ

主にUnityとC#に関する記事を書いていきます

【Unity】CustomEditor を UIElements を使って作成する

この記事では、uxml を使わずにスクリプトを使って CustomEditor を作成する方法を記述します

CustomEditor で UIElements を利用するには CreateInspectorGUI を override する必要があります

using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
 
public class UESampleBehaviour : MonoBehaviour
{
    [SerializeField]
    private int _intValue;
}
  
[CustomEditor(typeof(UESampleBehaviour))]
public class UESampleBehaviourEditor : Editor
{
    public override VisualElement CreateInspectorGUI()
    {
        // なにか処理を記述する
        return new VisualElement();
    }
}

従来の IMGUI を表示する

従来の IMGUI を表示するには IMGUIContainer を利用します

IMGUIContainerインスタンスを作成して root の VisualElement に Add すれば表示されます

f:id:hacchi_man:20201103170842p:plain:w300

   public override VisualElement CreateInspectorGUI()
    {
        var root = new VisualElement();
        var container = new IMGUIContainer(OnInspectorGUI);
        root.Add(container);

        return root;
    }

指定した Property を表示する

root の VisualElement に対して serializedObject を bind してから

var root = new VisualElement();
root.Bind(serializedObject);
  • PropertyField に SerializedProperty を指定する方法
  • bindingPath に Property の パスを指定する方法

の2つがあります

PropertyField では EditorGUILayout.PropertyField と同じく
SerializedProperty の型に合わせて適切な GUI が表示されます

f:id:hacchi_man:20201103171340p:plain:w300

   public override VisualElement CreateInspectorGUI()
    {
        var root = new VisualElement();
        root.Bind(serializedObject);
 
        // 直接 SerializedProperty を指定する
        var prop1 = new PropertyField(serializedObject.FindProperty("_intValue"), "Direction Prop");
        root.Add(prop1);
 
        // bindingPath で 対象の Property を指定する
        var prop2 = new PropertyField();
        prop2.label = "Bind Path";
        prop2.bindingPath = "_intValue";
        root.Add(prop2);
 
        return root;
    }

型を指定して 入力フィールドを表示する

PropertyField と同じように bindingPath を利用すれば Property の紐付けを行える

   public override VisualElement CreateInspectorGUI()
    {
        var root = new VisualElement();
        root.Bind(serializedObject);
 
        var intField = new IntegerField("IntegerField");
        intField.bindingPath = "_intValue";
        root.Add(intField);
 
        return root;
    }

型が一致していなくてもエラーは表示されませんが値が反映されません

   public override VisualElement CreateInspectorGUI()
    {
        var root = new VisualElement();
        root.Bind(serializedObject);
 
        var textField = new TextField("TextField");
        textField.bindingPath = "_intValue";
        root.Add(textField);
 
        return root;
    }