Chapter 03

エディター拡張の基礎

kumaS
kumaS
2021.02.25に更新

エディター拡張って何ができる?

Unity のエディター拡張はほんとにいろんなことができる。例えば、敵のデータを作成するみたいなものや、ちょっとした絵を描くなんてこともできる。アセットをインポートする時に特定の処理をするというのもそうだね。下にある私のものだってエディター拡張だよ。それじゃあ、ここでは主にエディター拡張の GUI はどうやって作るかについて書いていくよ。

https://github.com/kumaS-nu/NuGet-importer-for-Unity

エディター拡張のためのクラスを作る

今回はテキストを入力し、ボタンをクリックしたらコンソールにそのテキストを表示するようなエディター拡張を作るよ。下の gif のやつ。

Sample2

それじゃあ、まずはエディター拡張のためのクラスを作るよ。エディター拡張はエディター拡張というだけあってだいたいエディター上だけで動けばいいから、Editor フォルダを作って、その中にスクリプトを入れておくといいよ。

エディター拡張で、GUI を作るときは EditorWindow クラスを継承するよ。

EditorExtentionSample.cs
using UnityEditor;
using UnityEngine;

public class EditorExtentionSample : EditorWindow
{

}

ウィンドウを呼び出せるようにする

まずは、このエディター拡張のウィンドウを呼び出せるようにしよう。

EditorExtentionSample.cs
 using UnityEditor;
 using UnityEngine;

 public class EditorExtentionSample : EditorWindow
 {
+    [MenuItem("Test/Editor extention/Sample", false, 1)]
+    private static void ShowWindow()
+    {
+        EditorExtentionSample window = GetWindow<EditorExtentionSample>();
+        window.titleContent = new GUIContent("Sample Window");
+    }
 }

関数名に関してはなんでもいい[1]よ。では順番に見ていこう。
まず、最初の属性。[MenuItem()] は、Unity のメニューアイテム(File とか Edit とかあるところ)に新しいものを追加する属性だよ。追加されたものをクリックすると、属性がつけられた関数が実行されるんだ。ただ、関数に制約があって静的な関数じゃないとだめだよ。
引数については、今回は三つ全部使ったけど、一つでも二つでもいいよ。
一つめの引数は、どういうメニューアイテムを追加するかだよ。/ で階層を作るよ。
二つめの引数は、このボタンが使えるか判定するための関数かだよ。あまり使わないかなぁ。
三つめの引数は、メニューアイテムの並び順を指定するよ。数字が小さいほど上に行くよ。
GetWindow<エディター拡張のクラス>() を呼ぶことで、このエディター拡張のクラスの表示できるよ。返り値はこのクラスのオブジェクトが返ってくるんだ。
その次は、ウィンドウの名前を設定しているよ。デフォルトでは、このクラスの名前が設定されているんだけどそれじゃなんか嫌だからね。GUIContent は、タイトルだけじゃなくてツールチップや画像も設定できるよ。興味があったらやってみてもいいんじゃないかな?

描写する関数を作る

それじゃあ、描写するための関数を作るよ。描写する関数は OnGUI() という関数にするんだ。

EditorExtentionSample.cs
 using UnityEditor;
 using UnityEngine;

 public class EditorExtentionSample : EditorWindow
 {
     [MenuItem("Test/Editor extention/Sample", false, 1)]
     private static void ShowWindow()
     {
         EditorExtentionSample window = GetWindow<EditorExtentionSample>();
         window.titleContent = new GUIContent("Sample Window");
     }

+    private void OnGUI()
+    {
+       
+    }
 }

ウィンドウに文字を表示する

ウィンドウに文字を表示するには、GUILayout.Label() を使うよ。この場合は引数に文字列を入れているけど、テスクチャや GUIContent を入れていも表示してくれるよ。

EditorExtentionSample.cs
 using UnityEditor;
 using UnityEngine;

 public class EditorExtentionSample : EditorWindow
 {
     [MenuItem("Test/Editor extention/Sample", false, 1)]
     private static void ShowWindow()
     {
         EditorExtentionSample window = GetWindow<EditorExtentionSample>();
         window.titleContent = new GUIContent("Sample Window");
     }

     private void OnGUI()
     {
+        GUILayout.Label("この文字列を出力するよ");
     }
 }

文字列を入力する場所をつくる

一行だけ文字列を入力するのだったら EditorGUILayout.TextField() でいいんだけど、複数行入力したかったから EditorGUILayout.TextArea() を使うよ。
まずは、入力された文字列を覚えておくために変数を宣言するよ。
EditorGUILayout.TextArea() の一つめの引数には表示する文字列を入れるよ。
二つめの以降の引数には、この要素の見た目のオプションを入れれるよ。今回は複数行入れれるということを見せたかったから、高さを 100px にしたけど、無くてもいいよ。

EditorExtentionSample.cs
 using UnityEditor;
 using UnityEngine;

 public class EditorExtentionSample : EditorWindow
 {
     //初期化はいらないかもしれないけど怖くてやっちゃう
+    private var text = "";

     [MenuItem("Test/Editor extention/Sample", false, 1)]
     private static void ShowWindow()
     {
         EditorExtentionSample window = GetWindow<EditorExtentionSample>();
         window.titleContent = new GUIContent("Sample Window");
     }

     private void OnGUI()
     {
         GUILayout.Label("この文字列を出力するよ");
+        text = EditorGUILayout.TextArea(text, GUILayout.Height(100));
     }
 }

ボタンを作る

次はボタンを作るよ。GUILayout.Button() を使えばいいだけで、とっても簡単。
一つめの引数にはボタンに表示される文字列を書くよ。

EditorExtentionSample.cs
 using UnityEditor;
 using UnityEngine;

 public class EditorExtentionSample : EditorWindow
 {
     //初期化はいらないかもしれないけど怖くてやっちゃう
     private var text = "";

     [MenuItem("Test/Editor extention/Sample", false, 1)]
     private static void ShowWindow()
     {
         EditorExtentionSample window = GetWindow<EditorExtentionSample>();
         window.titleContent = new GUIContent("Sample Window");
     }

     private void OnGUI()
     {
         GUILayout.Label("この文字列を出力するよ");
         text = EditorGUILayout.TextArea(text, GUILayout.Height(100));
+        GUILayout.Button("コンソールに出力!!");
     }
 }

これで見た目はできたね。

ボタンがクリックされたらなにかする

さっき作った GUILayout.Button() の返り値を見てみると、bool になってるね。これは、クリックされたときに true になって、クリックされてないときは false になるんだ。だから、下のようにすれば、クリックされたときにコンソールに文字を出力できるんだ。
コンソールに文字を出力する方法は、みんな大好き Debug.Log() だよ!

EditorExtentionSample.cs
 using UnityEditor;
 using UnityEngine;

 public class EditorExtentionSample : EditorWindow
 {
     //初期化はいらないかもしれないけど怖くてやっちゃう
     private var text = "";

     [MenuItem("Test/Editor extention/Sample", false, 1)]
     private static void ShowWindow()
     {
         EditorExtentionSample window = GetWindow<EditorExtentionSample>();
         window.titleContent = new GUIContent("Sample Window");
     }

     private void OnGUI()
     {
         GUILayout.Label("この文字列を出力するよ");
         text = EditorGUILayout.TextArea(text, GUILayout.Height(100));
+        if (GUILayout.Button("コンソールに出力!!"))
+        {
+            Debug.Log(text);
+        }
     }
 }

どうだったかな?これで基礎は完了だ。あとは、チャプター 5 のチートシートのやつを組み合わせたり、公式のドキュメント(GUI 系のクラスを使うんだよ)を見てオリジナルのエディター拡張(の GUI)を作ろう!

OnGUI() が呼ばれるタイミング

あのコードで、ボタンクリックしたらちゃんと動くのかもやもやする人のために。
あのコードでちゃんと動く理由は、OnGUI() が呼ばれまくってるから。具体的に呼ばれるタイミングは、対象のコードが関連するイベントが発生したとき。例えば、ウィンドウにカーソルが入る・ウィンドウ内でカーソルが動く・ウィンドウ内でクリックされる・ウィンドウがフォーカスされた状態でキーボード入力されるなどなど。
そのたびに OnGUI() が呼ばれるのでちゃんとうごくわけ。自分で試したかったら、OnGUI() の先頭に Debug.Log() で何か出力するといい。

脚注
  1. さすがに既に使われている名前は除くよ。 ↩︎