パハットノート

主にUnity(C#)を中心としたプログラムの備忘録

Unity エディタ拡張(非publicリストの各要素に名前を付ける)





導入

前回(Unity エディタ拡張(publicリストの各要素に名前を付ける) - ミドリ黄のプログラミングメモノート)の記事ではpublicなリストに対してEditor拡張で要素の名前を変更したが、今回はprivateな変数などに対しても編集できるようにする




作成したクラス

Enemyクラス

  • 敵のステータスを保存するためのクラス
  • このクラスのリスト「stats」をエディタ拡張により表示するのが今回の目的。
using System.Collections.Generic;
using UnityEngine;

public enum Stat
{
    Hp,
    Attack,
    Defense,
}

public class Enemy : MonoBehaviour
{
    [SerializeField] List<int> stats;
}



エディタ拡張のためのクラス

解説は後述

using UnityEngine;
using UnityEditor;
using System;

[CustomEditor(typeof(Enemy))]
public class EnemyEditor : Editor
{
    int ListSize => Enum.GetValues(typeof(Stat)).Length;//enum Statの長さ
    SerializedProperty prop;//statsを格納する

    private void OnEnable()
    {
        //statsを取得
        prop = serializedObject.FindProperty("stats");

        //配列の長さを指定
        if (prop.arraySize != ListSize)
        {
            //更新
            serializedObject.Update();

            prop.arraySize = ListSize;

            //保存
            serializedObject.ApplyModifiedProperties();
        }       
    }

    public override void OnInspectorGUI()
    {
        //更新
        serializedObject.Update();

        //リストの名前を記載
        EditorGUILayout.LabelField("ステータス");

        //各要素を描画
        for (int i = 0; i < ListSize; i++)
        {
            //表示するステータス名前
            Stat stat = (Stat)Enum.ToObject(typeof(Stat), i);

            //表示
            EditorGUILayout.PropertyField(prop.GetArrayElementAtIndex(i), new GUIContent(stat.ToString()));
        }

        //保存
        serializedObject.ApplyModifiedProperties();
    }
}




プログラムの解説

[CustomEditor(typeof("編集したいクラス名"))]

  • 編集するクラス名を設定することができます。



serializedObject

  • 自分自身も正確には把握できていませんが、現在は、「『CustomEditor』で指定したスクリプトがアタッチされているオブジェクトの情報(?)」という風に考えています。



serializedObject.FindProperty("編集する変数名")

  • 「CustomEditor」で指定したクラスの指定した変数をSerializedProperty型で取り出せます。
  • privateな変数でも参照することが可能です。



void OnEnable()

  • 「CustomEditor」で指定したクラスをアタッチしたGameObjectなどを選択したときに呼び出されます。
  • 初期設定などに使用



SerializedProperty.arraySize

  • SerializedPropertyが配列やリストであったときのその長さを示す
  • SerializedPropertyが配列やリストでないときはエラー



public override void OnInspectorGUI()

  • MonoBehaviorのUpdate関数のように繰り返し呼び出されます。
  • メインの処理を記述します。



serializedObject.Update() & serializedObject.ApplyModifiedProperties()

  • 変更を保存したり、オブジェクトの更新などに使用
  • 詳しい働きはよくわかんないです。



EditorGUILayout.LabelField("文字列");

  • 指定した文字列をインスペクター上に表示します。
  • 幅はEditorGUIUtility.labelWidthを書き換えることで変更できます(今回は変更なし)。



SerializedProperty.GetArrayElementAtIndex(i)

  • 指定したSerializedPropertyが配列やリストであったときに、そのi番目の要素をSerializedProperty型で取得



EditorGUILayout.PropertyField(SerializedProperty, new GUIContent(stat.ToString()));

  • SerializedPropertyをインスペクターに表示します。
  • 第2引数で表示名などを設定できます。
  • int, string, Listなど大体の型は表示できた。





動作確認

Enemyクラスをシーン上の任意のゲームオブジェクトにアタッチするとこのように編集できます。