Unityでは自分でウィンドウを作れる【Editor拡張を使おう】

Unityでは自分でウィンドウを作れる【Editor拡張を使おう】

UnityではEditor拡張として、普段使っているUnityエディタの機能を自分でカスタマイズすることができます。

例えば私がアセットストアで公開しているアセットではペイントのようにマス目にダンジョンのパーツを塗っていくことでその通りにダンジョンを生成する機能がありますが、このダンジョンのパーツを塗るウィンドウはC#で書いています。こんな感じの画面を自分でEditor拡張で作ることができるんです。

MapEditor
MapEditor

 

コードの中でテクスチャを生成して画面に表示することもできるので、調べてみると案外たくさんのことができたりします。

こんな感じで必要に応じてウィンドウを作成することができるので、RPGでの戦闘シミュレーションや必要経験値表などを表示することもできます。

開発中に自分でゲームを実行して戦闘のゲームバランスを確認していくのは中々大変なので、こうしたエディタ機能やデバッグ機能を用意しておくと開発が楽になります。

このページではEditor拡張の概要に触れつつ、オリジナルのウィンドウを作るところまでやってみましょう。

 

 

環境

macOS 10.15 Catalina

Unity2019.4.4f1

 

Editor(エディタ)拡張について

Editor(エディタ)拡張とは、Unityのエディタ機能を拡張するための機能です。そのまんま。

「エディタの機能を拡張する」とはどういうことかというと、例えばUnityのエディタが標準で表示していない情報を画面に表示したり、自分が作ったデータの一覧や特定の情報をまとめて表示するなど、標準には存在しない機能を自分で追加できるんです。

初心者の頃はUnityの使い方に慣れるのに精一杯でしたが、慣れてくるとだんだん「こんな機能が欲しいな」と欲が出てきます。マニュアルを探して見つかる場合もありますが、そうでない場合は諦めるか自分で作るかが選択肢に。自分で作る場合にはUnityのエディタに機能を追加するEditor拡張を使うことで実装できます。

Editor拡張の概要や簡単な機能追加については以下の記事もご参照ください。

 

 

 

Editor拡張でパーツを表示するには

Editor拡張ではC#を使って機能とレイアウトの両方を記述していきます。

UIを描画するにもC#を使うというのは、普段ゲームの中でuGUIを使っていると「おや?」と思うかもしれません。UnityだとUIを表示するための方法として以下の3つがあります。

  • IMGUI
  • UGUI(Unity UI)
  • UIElements

これらについて簡単に触れていきます。

 

IMGUI

IMGUI(Immediate Mode Graphical User Interface: 即時モードのGUI)はゲームオブジェクトに依存しない形でUIのパーツを描画する機能です。マニュアルには「主にプログラマー用のツール」とあり、エディタ拡張ではこのIMGUIを使い、C#で記述します。

元々はUnityのGUIといえばIMGUIがメインでしたが、後からUGUI(小文字のuGUI表記の場合も)が追加されたのでした。(後からと言っても2015年ごろ?)

ゲーム実行中は事前に保持されたUIの情報をゲームオブジェクトとして使うのが便利なのでUGUIが作られてからはこちらが主流になったのでした。

IMGUIはコードベースで記述し、そのコードが呼ばれるタイミングでGUIのパーツを描画します。ゲームの実行中は毎フレームこの処理を実行することでちょっと負荷がかかることから新しいUGUIのシステムが作成されたようです。また、デザイナーが画面を見ながら配置するということができないのでレイアウト的な意味でもちょっと大変な部分でした。

一方でIMGUIはイベントベース(例えば画面をクリックしたタイミング、値を入力したタイミング)などで更新の必要が出たときに呼び出されるには都合が良いのでエディタでは現在でも使われています。

歴史的経緯についてはちょっと不正確な部分もあると思うので他のブログ(Unity Blogやテラシュールブログさん)などで過去記事をあさってみると流れを掴めると思います。

ちなみに私がUnityを使い始めた頃にはIMGUIの情報が多く、UGUIと混同して区別がついていなかった記憶があります。チュートリアル動画などではUGUIを使った形式になっていた記憶があるのでUGUIが出た後だとは思いますが、UIシステムの情報が2つあるカオスな時期に使い始めたのは今思えばすごい状況だったと思います。

それがまさかエディタ拡張に手を出してIMGUIもUGUIも使うようになるとは……(笑)

 

UGUI(Unity UI)

ゲーム内でゲームオブジェクトとしてUIを表示する機能はUGUIです。Unity2019からは呼び方がUnity UIになったようです。相変わらずUGUIと呼んでいる人も多く、技術ブログで検索する場合にもUGUI(あるいはuGUI)の表記が多いかもしれません。

事前にゲームオブジェクトとしてシーンに表示できるので、プログラマーだけでなくデザイナーが画面からいい感じに配置しやすい利点があります。他にもCanvasを使うことで様々なデバイスの画面に合わせたUIの表示が可能になっている点も便利ポイントですね。

と、この辺りはいつも使っていてご存知の部分かと思います。

 

UIElements(UIエレメンツ)

Unity2019からはUIElements(UIエレメンツ)と呼ばれるUIシステムもあります。このシステムは現在エディタ上で使える機能で、今後はゲームの実行時にも使えるようになるそうです。

UIElementsではパーツの構造をUXMLで、パーツのスタイルをUSSでそれぞれ記述します。Web系に触ったことのある方ならHTML+CSSのイメージで入りやすいと思います。

まだ実験的な機能の位置付けですが、GraphViewの機能を使うことでノードベースの画面を作ることもできます。パッケージのソースコードを確認してみると、Visual Effect GraphやShader GraphはこのAPIを使って実装されているようです。

ノードベースの画面はプログラミングに慣れていない人でも操作しやすくなるので、チーム内でアーティストが画面をちょっといじって調整する、みたいな拡張も用意できるかもしれません。また、アーティストならスタイルシートも慣れているかもしれませんからそこで共同で進めるのも良さそうです。

 

Editor拡張のウィンドウの話

とまぁUIの話になっちゃいましたが、ゲーム内のデータを整理して表示したり、なんらかのアクションを実行したりと自分専用のウィンドウを作っておくのも便利です。

プログラマー自身が自分で使う分にはデザインもそこまで気にしなくてもいい気もしますから、C#でドバーッと書いちゃってみると良いと思います。(もちろんデザインも意識できれば最高ですが時間との兼ね合いを考えてうまくやってみてくださいな)

ここでは試しにメニューバーから開くことのできるウィンドウを作ってみたいと思います。

 

Editorフォルダとスクリプトの作成

まずはEditorフォルダを作成します。このフォルダは特殊な役割を持ったフォルダで、このフォルダ内に配置したスクリプトはゲームのビルド時にコンパイルの対象から外してくれます。というのも、エディタ用のスクリプトをゲームに持っていくのはよくないですからね。

エディタ用スクリプトを書く際は「UnityEditor」のディレクティブを宣言しますが、この名前空間のモジュールはビルド時に含まれないのでコンパイルエラーが発生するようになっています。

このフォルダ名に関してはマニュアルの以下の記事でも解説されています。

 

というわけでフォルダを作成しましょう。Assetsフォルダの下に [Editor] フォルダを作成します。

Editorフォルダ
Editorフォルダ

 

『Editor』フォルダを開いてスクリプトファイルを作成します。名前はなんでもいいですがここでは [MyWindow] にしました。

スクリプトファイル
スクリプトファイル

 

ウィンドウを表示してみる

スクリプトを開いたらウィンドウを表示する処理を書いていきます。

 

using UnityEditor;」でエディタ用のクラスを使えるようにしています。

ウィンドウを表示するため、継承するのはMonoBehaviourではなく「EditorWindow」に変更します。Start()やUpdate()は使わないので削除しておきましょう。

ウィンドウを表示するためのメソッドは「Open()」です。メソッド名はメッセージ関数と重複していなければ自由に付けられるので、個人的にわかりやすくするために「Open()」にしています。属性として [MenuItem(パス)] をつけることによって、メニューバーでその通りの場所に表示され、メニューとして選択された際にこのメソッド(ここでは「Open()」)が呼び出されます。ここでは「Window」メニューの下に表示するようにしていますが、デフォルトのメニュー項目にない文字列を指定した場合は新たにその項目がメニューに表示されるようになります。

実際にウィンドウを開くのはメソッド内の処理で、GetWindow<T>を使っています。このメソッドはstaticなメソッドで画面内に指定したウィンドウがあればそれを表示し、なければ新しくインスタンスを作成します。

titleContentのフィールドにはGUIContentでインスタンスを作ってウィンドウのタイトルを設定しています。日本語でも表示できるのでここでは「オリジナルのウィンドウ」とそのまま入力しています。GUIContentではアイコンも指定することができます。

 

スクリプトを保存したらメニューバーから開いてみましょう。MenuItemの属性で指定したパスから「MyWindow」を選択します。

メニューから開くのだポッター
メニューから開くのだポッター

 

作成したウィンドウが以下のように表示されます。ウィンドウの名前としてタブに「オリジナルのウィンドウ」が表示されています。この段階ではウィンドウそのものを表示する処理しか追加していないので、中身は何も表示されていません。

吾輩はウィンドウである。パーツはまだない。
吾輩はウィンドウである。パーツはまだない。

 

テキストを追加してみる

ウィンドウにテキストを表示してみます。

OnGUI()のメソッドでどんなパーツを描画するか記載しています。EditorGUILayoutのクラスを使うことである程度自動的にレイアウトをした状態でパーツを表示してくれます。BeginVertical()は「ここから縦にパーツを配置します」という宣言で、引数でスタイルを指定することができます。EndVertical()まで差し掛かったところで縦のレイアウトを終了します。

もうひとつのBeginHorizontal()は「ここから横にパーツを配置します」という宣言で、同様にEndHorizontal()までの間に記載したパーツを横に並べてくれます。

LabelField()は文字を表示するためのフィールドです。文字入力を行いたい場合はTextField()を使います。

Space()を使うことでスペースを表示することができます。

上のスクリプトの中ではインデントを使って、どこからどこまでがひとつの塊なのかを分かるようにしています。この辺りは自分で分かりやすい方法でまとめると良いと思います。私はこのインデント方式か中かっこ{}を使って範囲が分かるようにしています。

 

スクリプトを保存してウィンドウを開くと以下のように表示されます。Boxのスタイルを指定した部分は色が変わって箱型でまとめられています。

パーツが表示された
パーツが表示された

 

ここでは文字を表示するだけでしたが、テクスチャを表示したり値を入力するフィールドを表示することもできるので自由にカスタマイズすることができます。例えば自分で定義したScriptableObjectのデータを読み込んでそれを一覧として表示する、というのも便利かもしれません。

EditorGUILayoutについてはスクリプトリファレンスを眺めてみるといろいろなパーツを使いたくなるかもしれません。

 

まとめ

必要な機能を持った画面を作る場合はゲーム開発に限らず業務アプリなどの画面設計なども参考になります。ここまでできるようになると、Unityでのゲーム開発に加えて業務ソフトの開発にも手を出せるかもしれません。

……逆に業務ソフトの開発をしている人がEditor拡張に手を出していることが多いかもしれませんが(笑)

Editor拡張は最初は悩むことも多いですが、慣れれば開発便利ツールをホイホイ作れるのでゲーム開発が落ち着いたときに触れてみるのも楽しいと思います。例えばプロジェクトの振り返りを行っている際、「ここを自動化できたら楽だなー」とかそういった要望が出てくるかと思うので、その部分をEditor拡張で実装することから始めるのも良さそうです。

 

     

ゲーム開発の攻略チャートを作りました!

CTA-IMAGE

「ゲームを作ってみたいけど、何から手を付けていいか分からない!」


そんなお悩みをお持ちの方向けに、todoがアプリをリリースした経験を中心に、ゲーム作りの手順や考慮すべき点をまとめたe-bookを作成しました。ゲーム作りはそれ自体がゲームのように楽しいプロセスなので、「攻略チャート」と名付けています。


ゲームを作り始めた時にぶつかる壁である「何をしたら良いのか分からない」という悩みを吹き飛ばしましょう!