topaz-dev’s

ああああああ

Unity エディタ拡張 基本テンプレ

エディタウィンドウ、カスタムエディタ、PropertyDrawerを作る際の基本的な内容をまとめたメモ。

エディタウィンドウの作成

  • EditorWindowを継承する
  • MenuItemAttributeをつけてWindowを呼び出すツールバーを作成する
  • OnGUI() に表示内容を書く
using UnityEngine;
using UnityEditor;

public class MyWindow : EditorWindow
{
    [MenuItem("MyWindow/Open")]
    public static void ShowWindow()
    {
        MyWindow window = EditorWindow.GetWindow<MyWindow>();
        window.Show();

    }
    private void OnGUI()
    {
        if (GUILayout.Button("ボタンです"))
        {
            Debug.LogWarning("ボタンが押されました");
        }
    }
}

ツールバーの表示(MenuItemによる表示)

MyWindow/Openが追加される

Windowの表示

作成したWindowが表示されボタンを押すとログが出力される。

カスタムエディタ(インスペクター)の作成

  • CustomEditorAttributeを付け、Editorを継承する
  • OnEnable()で表示(変更)したいプロパティを取得する
    FindPropertyの引数にはPlayerクラスの変数名を指定する(typoに注意)
  • OnInspectorGUIをoverrideして表示内容を書く
    初めにserializedObject.Update();、終わりにserializedObject.ApplyModifiedProperties();を呼ぶようにする。
// Player.cs
using UnityEngine;

public class Player : MonoBehaviour
{
    public string _name;
    public int _hp;
    public int _speed;
}
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(Player))]
public class PlayerEditor : Editor
{
    SerializedProperty _name;
    SerializedProperty _hp;
    SerializedProperty _speed;
    private void OnEnable()
    {
        // プレイヤークラスのプロパティを取得する
        _name = serializedObject.FindProperty("_name");
        _hp = serializedObject.FindProperty("_hp");
        _speed = serializedObject.FindProperty("_speed");
    }
    public override void OnInspectorGUI()
    {
        // 描画更新する
        serializedObject.Update();

        Color defaultColor = GUI.color;
        GUI.color = Color.yellow;
        GUILayout.Label("プレイヤーのカスタムエディタ");
        GUI.color = defaultColor;

        // 標準の表示方法
        EditorGUILayout.PropertyField(_name);
        // カスタム表示
        using (var w = new EditorGUILayout.HorizontalScope())
        {
            GUILayout.Label("プレイヤーの体力");
            _hp.intValue = EditorGUILayout.IntField(_hp.intValue);
        }
        // カスタム表示
        using (var w = new EditorGUILayout.HorizontalScope())
        {
            GUILayout.Label("移動速度");
            _speed.intValue = EditorGUILayout.IntSlider(_speed.intValue, 0, 100);
        }


        // 変更を保存する
        serializedObject.ApplyModifiedProperties();
    }
}

変更前

変更後

プロパティドローワー

  • CustomPropertyDrawerAttributeを付け,PropertyDrawerを継承する
  • OnGUI()をoverrideして表示内容を書く
    EditorGUILayoutGUILayoutが使えないため、GUIを使って描画座標と範囲(Rect)を指定しなくてはいけない。
  • GetPropertyHeight()をoverrideして、プロパティが占領する高さを指定する
// Equipment.cs
[System.Serializable]
public class Equipment
{
    public string _weapon;
    public string _armor;
    public string _boots;
}
// Player.cs
using UnityEngine;
public class Player : MonoBehaviour
{
    public string _name;
    public int _hp;
    public int _speed;
    [SerializeField] Equipment _equipment;
}
using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(Equipment))]
public class EquipmentDrawer : PropertyDrawer
{
    private int height = 20;
    private int marginHeight = 2;
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        var _weaponProp = property.FindPropertyRelative("_weapon");
        var _armorProp = property.FindPropertyRelative("_armor");
        var _bootsProp = property.FindPropertyRelative("_boots");
        position.height = height;

        // トップラベル
        Color defaultColor = GUI.color;
        GUI.color = Color.yellow;
        GUI.Label(position, "====装備品====");
        position.y += height + marginHeight;
        GUI.color = defaultColor;

        var labelPosition = position;
        labelPosition.width = 100;
        position.x += 120;

        // 武器
        GUI.Label(labelPosition, "武器");
        _weaponProp.stringValue = GUI.TextField(position, _weaponProp.stringValue);
        position.y += height + marginHeight;
        labelPosition.y += height + marginHeight;

        // 防具
        GUI.Label(labelPosition, "防具");
        _armorProp.stringValue = GUI.TextField(position, _armorProp.stringValue);
        position.y += height + marginHeight;
        labelPosition.y += height + marginHeight;

        // ブーツ
        GUI.Label(labelPosition, "ブーツ");
        _bootsProp.stringValue = GUI.TextField(position, _bootsProp.stringValue);
    }
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        return height * 4 + marginHeight * 3;
    }
}

変更前

変更後

プロパティドローワーのリストでの表示

プロパティドローワーはProperFieldの表示を変えるものになるため、リストで表示した際に全てに適用される。

public class Player{
    // 省略
    public List<Equipment> equipment;
}

まとめ

エディタ拡張を使うことで、開発効率あげ楽しく行うことが出来る。
他にもたくさん機能がありもっと自由にカスタマイズす流ことが出来る。