MRが楽しい

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

UnityのInspectorビューにクラスの関数に合わせて関数を実行するボタンを自動で追加する

本日は Unity の小ネタ枠です。
UnityのInspectorビューにクラスの関数に合わせて関数を実行するボタンを自動で追加する手順を記事にします。
f:id:bluebirdofoz:20210716235527j:plain

前提条件

前回記事の続きです。
bluebirdofoz.hatenablog.com

Type.GetMethods

クラスのメソッドの一覧を取得します。
引数の BindingFlags タイプを変更することで様々な定義のメソッドを指定して取得できます。
docs.microsoft.com
docs.microsoft.com

MethodBase.GetParameters

メソッドが持つ引数の情報一覧を取得します。
docs.microsoft.com

サンプルスクリプト

以下のサンプルスクリプトと、そのエディター拡張を行うスクリプトを作成しました。
エディター拡張では拡張対象のクラスのメソッド一覧を取得し、そのクラス階層が持つ引数のない Public な関数の実行ボタンを自動で追加します。
・TestScript.cs

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

/// <summary>
/// サンプルスクリプト
/// </summary>
public class TestScript : MonoBehaviour
{
    /// <summary>
    /// Public関数(引数無し)
    /// </summary>
    public void PublicMethod()
    {
        Debug.Log("PublicMethod");
    }

    /// <summary>
    /// Public関数(引数有り)
    /// </summary>
    public void ArgPublicMethod(string message)
    {
        Debug.Log("PublicMethod : " + message);
    }

    /// <summary>
    /// Private関数
    /// </summary>
    private void PrivateMethod()
    {
        Debug.Log("PrivateMethod");
    }
}

f:id:bluebirdofoz:20210716235603j:plain

・TestMessageScriptEditor.cs

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

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

using UnityEditor;
using System.Reflection;

// 拡張するクラスを指定する
[CustomEditor(typeof(CUSTOMTYPE))]
public class TestScriptEditor : Editor
{
    // GUIの表示関数をオーバーライドする
    public override void OnInspectorGUI()
    {
        // 元のインスペクター部分を表示
        base.OnInspectorGUI();

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

        // Editor実行中のみ有効化なUIを設定する
        if (EditorApplication.isPlaying)
        {
            // Publicかつ指定したクラス階層のメソッドのみの一覧を取得する
            BindingFlags flag = BindingFlags.Public |
                BindingFlags.Instance | BindingFlags.DeclaredOnly;
            MethodInfo[] methods = targetScript.GetType().GetMethods(flag);

            foreach (MethodInfo method in methods)
            {
                // メソッドの引数一覧を取得する
                ParameterInfo[] methodParam = method.GetParameters();

                // 引数がない関数のみ実行ボタンを作成する
                if (methodParam.Length == 0)
                {
                    // public関数を実行するボタンの作成
                    if (GUILayout.Button(method.Name + "の実行"))
                    {
                        method.Invoke(targetScript, null);
                    }
                }
            }
        }
    }
}
#endif

f:id:bluebirdofoz:20210716235614j:plain

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

動作確認

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

対象クラスの関数が自動的に検出されて Inspectro ビューに関数を実行する拡張UIが表示されました。
f:id:bluebirdofoz:20210716235646j:plain