この記事でのバージョン
Unity 5.3.4f1 Personal
はじめに
特定のメソッドをInspectorから実行できるようにしておくと便利な場合は多々あると思いますが、
そんな時に一番楽なのはContextMenuだと思います。
//Inspectorの歯車アイコンにMethodという項目を追加、押すと下のメソッドが実行される [ContextMenu("Method")] private void Method () { }
ただ、使う側からするとパッと見でInspectorから実行できるメソッドがあるとは分からない
ので、少々不便かもしれません。
という事で今回はInspectorにメソッドを実行するボタンを追加する方法のご紹介です!
CustomEditor
Inspectorの表示を変えるにはEditorというクラスを継承したクラスを作成し、
CustomEditorという属性で拡張したいクラスを指定します。
例えばExampleScriptというクラスと、
そのExampleScriptのInspectorを拡張するExampleScriptEditorを
作ってみると、以下のようになります。
using UnityEngine; public class ExampleScript : MonoBehaviour { }
using UnityEditor; using UnityEngine; [CustomEditor(typeof(ExampleScript))]//拡張するクラスを指定 public class ExampleScriptEditor : Editor { /// <summary> /// InspectorのGUIを更新 /// </summary> public override void OnInspectorGUI(){ } }
上記のままだとOnInspectorGUIで何もしていないのでインスペクターには何も表示されません。
base.OnInspectorGUIを書けば、継承元の元のOnInspectorGUIが実行されるので、
拡張しない場合と同じGUIが表示されます。
using UnityEditor; using UnityEngine; [CustomEditor(typeof(ExampleScript))]//拡張するクラスを指定 public class ExampleScriptEditor : Editor { /// <summary> /// InspectorのGUIを更新 /// </summary> public override void OnInspectorGUI(){ //元のInspector部分を表示 base.OnInspectorGUI (); } }
ボタンを表示したい場合はGUILayout.Buttonをifの条件として使います。
ボタンが押されるとif内部の処理が実行される感じです。
using UnityEditor; using UnityEngine; [CustomEditor(typeof(ExampleScript))]//拡張するクラスを指定 public class ExampleScriptEditor : Editor { /// <summary> /// InspectorのGUIを更新 /// </summary> public override void OnInspectorGUI(){ //元のInspector部分を表示 base.OnInspectorGUI (); //ボタンを表示 if (GUILayout.Button("Button")){ Debug.Log("押した!"); } } }
さらに、targetで拡張している対象を取得できるので、
それを変換すれば対象のメソッドを実行できるようになります。
using UnityEngine; public class ExampleScript : MonoBehaviour { //表示したログ、SerializeFieldを付ける事でInspectorに表示されるように [SerializeField] private string _log = ""; /// <summary> /// _logを"ぷぅあぶりっく!"に変更してConsoleに表示 /// </summary> public void PublicMethod(){ _log = "ぷぅあぶりっく!"; Debug.Log(_log); } }
using UnityEditor; using UnityEngine; [CustomEditor(typeof(ExampleScript))]//拡張するクラスを指定 public class ExampleScriptEditor : Editor { /// <summary> /// InspectorのGUIを更新 /// </summary> public override void OnInspectorGUI(){ //元のInspector部分を表示 base.OnInspectorGUI (); //targetを変換して対象を取得 ExampleScript exampleScript = target as ExampleScript; //PublicMethodを実行する用のボタン if (GUILayout.Button("PublicMethod")){ exampleScript.PublicMethod (); } } }
privateなメソッドはそのままだと実行できないので、
SendMessageを使って実行すると楽かと思います。
なお、ExecuteInEditModeを使わないとエラーが出るので注意が必要です。
using UnityEngine; [ExecuteInEditMode] //SendMessageでエラーが出ないように public class ExampleScript : MonoBehaviour { //表示したログ、SerializeFieldを付ける事でInspectorに表示されるように [SerializeField] private string _log = ""; /// <summary> /// _logを"ぷらいべーと!"に変更してConsoleに表示 /// </summary> private void PrivateMethod(){ _log = "ぷらいべーと!"; Debug.Log(_log); } }
using UnityEditor; using UnityEngine; [CustomEditor(typeof(ExampleScript))]//拡張するクラスを指定 public class ExampleScriptEditor : Editor { /// <summary> /// InspectorのGUIを更新 /// </summary> public override void OnInspectorGUI(){ //元のInspector部分を表示 base.OnInspectorGUI (); //targetを変換して対象を取得 ExampleScript exampleScript = target as ExampleScript; //PrivateMethodを実行する用のボタン if (GUILayout.Button("PrivateMethod")){ //SendMessageを使って実行 exampleScript.SendMessage ("PrivateMethod", null, SendMessageOptions.DontRequireReceiver); } } }
おわりに
楽に実装できるのはContextMenuなのですが、
使い勝手でみれば今回紹介した方法のがいいかと思います。
まぁ、状況に応じてといった感じでしょうか(:3っ)∋〜