MRが楽しい

MRやVRについて学習したことを書き残す

SerializedPropertyを使ってEditor拡張でクラスのプロパティの表示をカスタマイズする

本日は Unity の小ネタ枠です。
SerializedPropertyを使ってEditor拡張でクラスのプロパティの表示をカスタマイズする方法を試してみます。

SerializedPropertyとSerializedObject

SerializedProperty と SerializedObject はオブジェクトのプロパティを編集するためのクラスです。
docs.unity3d.com
docs.unity3d.com

本記事では以下のクラスを組み合わせてエディター再生中にのみプロパティの表示を行う拡張を実施してみました。

HideInInspector

HideInInspector は public プロパティを非表示にすることができます。
docs.unity3d.com

サンプルスクリプト

以下のサンプルスクリプトと、そのエディター拡張を行うスクリプトを作成しました。
・TestPropertyScript.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// サンプルスクリプト
/// </summary>
public class TestPropertyScript : MonoBehaviour
{
    [System.Serializable]
    public class IdAndName
    {
        public int id;
        public string name;
    }

    // Editor から FindProperty で取得するため
    // public または SerializeField としておく
    [HideInInspector]
    public IdAndName p_IdAndName;

    private void Start()
    {
        p_IdAndName.id = 10;
        p_IdAndName.name = "Tests";
    }

    /// <summary>
    /// デバッグメッセージを表示するPublic関数
    /// </summary>
    public void PublicMyMessageMethod()
    {
        Debug.Log("PublicMyMessageMethod : " + p_IdAndName.id.ToString() + ", " + p_IdAndName.name);
    }

    /// <summary>
    /// デバッグメッセージを表示するPrivate関数
    /// </summary>
    private void PrivateMyMessageMethod()
    {
        Debug.Log("PrivateMyMessageMethod : " + p_IdAndName.id.ToString() + ", " + p_IdAndName.name);
    }
}

f:id:bluebirdofoz:20210817224215j:plain

・TestPropertyScriptEditor.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

#if UNITY_EDITOR
using UnityEditor;

// クラス名を別名でまとめて管理する
using CUSTOMTYPE = TestPropertyScript;

// 拡張するクラスを指定する
[CustomEditor(typeof(CUSTOMTYPE))]
public class TestPropertyScriptEditor : Editor
{
    // 参照プロパティ
    private SerializedProperty p_MyIdAndNameProperty;
    private SerializedProperty p_IdProperty;
    private SerializedProperty p_NameProperty;

    private void OnEnable()
    {
        // 拡張対象クラスから変数のプロパティを取得する
        p_MyIdAndNameProperty = serializedObject.FindProperty("p_IdAndName");
        p_IdProperty = p_MyIdAndNameProperty.FindPropertyRelative("id");
        p_NameProperty = p_MyIdAndNameProperty.FindPropertyRelative("name");
    }

    // GUIの表示関数をオーバーライドする
    public override void OnInspectorGUI()
    {
        // 元のインスペクター部分を表示
        base.OnInspectorGUI();

        // targetを変換して対象スクリプトの参照を取得する
        CUSTOMTYPE targetScript = target as CUSTOMTYPE;

        // Editor実行中のみ有効化なUIを設定する
        if (EditorApplication.isPlaying)
        {
            // public関数を実行するボタンの作成
            if (GUILayout.Button("PublicMyMessageMethodの実行"))
            {
                targetScript.PublicMyMessageMethod();
            }

            // private関数を実行するボタンの作成
            if (GUILayout.Button("PrivateMyMessageMethodの実行"))
            {
                targetScript.SendMessage("PrivateMyMessageMethod", SendMessageOptions.DontRequireReceiver);
            }

            // プロパティの表示フィールド
            serializedObject.Update();

            p_IdProperty.intValue = EditorGUILayout.IntField(p_IdProperty.intValue);
            p_NameProperty.stringValue = EditorGUILayout.TextField(p_NameProperty.stringValue);

            serializedObject.ApplyModifiedProperties();
        }
    }
}
#endif

f:id:bluebirdofoz:20210817224227j:plain

シーンの適当なオブジェクトにサンプルスクリプトを設定します。
f:id:bluebirdofoz:20210817224238j:plain

動作確認

シーンを再生して動作を確認するため、Unity エディターの[再生]ボタンをクリックします。
f:id:bluebirdofoz:20210817224248j:plain

シーンが再生中のみ、Inspectro ビューにプロパティを入力する拡張UIが表示されました。
f:id:bluebirdofoz:20210817224258j:plain
f:id:bluebirdofoz:20210817224307j:plain