🦄 インスペクタウィンドウからメソッドを呼ぶ方法色々

2021-05-22 #Unity

Unityで開発している途中に、デバッグ用にインスペクタウィンドウにボタンを追加するスクリプトを度々書くんだけど、案外面倒なので使いまわせるやつを作ってみました。

あと、ついでに普通のやり方法も忘れないようにメモ。

コンテキストメニューからメソッドを呼ぶ

一番簡単なやつ。ギアアイコンから実行できるようになります。

[ContextMenu("PrivateMethod")]
private void PrivateMethod()
{
    print("PrivateMethod");
}

インスペクタウィンドウからメソッドを呼ぶボタンを追加する

ちゃんとボタンを追加したい場合には下記みたいな感じで書きます。

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

#if UNITY_EDITOR
using UnityEditor;
#endif

[ExecuteAlways]
public class Example : MonoBehaviour
{
    public void PublicMethod()
    {
        print("PublicMethod");
    }

    private void PrivateMethod()
    {
        print("PrivateMethod");
    }
}

#if UNITY_EDITOR
[CustomEditor(typeof(Example))]
public class ExampleEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        Example t = target as Example;

        if (GUILayout.Button("PublicMethod"))
        {
            t.PublicMethod();
        }

        if (GUILayout.Button("PrivateMethod"))
        {
            t.SendMessage("PrivateMethod", null, SendMessageOptions.DontRequireReceiver);
        }
    }
}
#endif

インスペクタウィンドウからメソッドを呼ぶボタンをインスペクタウィンドウから追加する

UnityEventを中継するように書いておけば、個別に呼び出したいメソッド毎にスクリプトを書かなくてもInspectorからメソッドが追加できるようになります。

1つのUnityEventに対して複数のリスナーを追加して一気にInvokeさせて動かす事もできますが、Inspectorのボタンのラベルは1つ目のメソッドの名前が自動で表示されます。 ボタンを増やしてそれぞれ別個に発火させたい場合にはListに新たにUnityEventを追加していきます。

[ExecuteAlways]
public class MethodCaller : MonoBehaviour
{
    public List<UnityEvent> OnEvent;

    public void Action(int id)
    {
        OnEvent[id].Invoke();
    }
}

#if UNITY_EDITOR
    [ExecuteAlways]
    [CustomEditor(typeof(MethodCaller))]
    public class MethodCallerEditor : Editor
    {
        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();

            MethodCaller t = target as MethodCaller;
            if (t == null) return;
            if (t.OnEvent == null) return;
            if (t.OnEvent.Count > 1)
            {
                for (int i = 0; i < t.OnEvent.Count; i++)
                {
                    if (t.OnEvent[i].GetPersistentEventCount() > 0 && t.OnEvent[i].GetPersistentMethodName(0).Length > 0)
                    {
                        if (GUILayout.Button(t.OnEvent[i].GetPersistentMethodName(0)))
                        {
                            t.Action(i);
                        }
                    }
                }
            }
        }
    }
#endif

ついでなのでGitHubにアップしておきました。

https://github.com/is8r/example-MethodCaller

もっと複雑な事がしたくなったらアップデートするかも…

Profile
😛

石原 悠 / Yu Ishihara

デザインとプログラミングとヨーグルト作りが好きです。