UnityのEditor拡張をしてインスペクタをカスタマイズする

今回はUnityのEditor拡張を利用してインスペクタで表示されるデータのカスタマイズをしてみたいと思います。

エディターの拡張を使えるようになるとゲーム開発の効率がよくなります。

よくなりますと適当に言っている感じは否めないですが・・・・(^_^;)

ゲーム開発を一人でやる人もいますが通常は複数人が関わってゲームを開発する事が多いと思います。

例えば『ゲーム全般を見る人』『キャラクター等の制作を担当する人』『プログラミングをする人』『ゲームの音楽を担当する人』等です。

キャラクターを制作した人がゲーム内でのキャラクターの動きを確認したい時にキャラクターを動かす時のパラメータを操作し動きを細かく確認したいとします。

ですが通常はインスペクタで設定のパラメータと値だけが表示されており、プログラミングをした人はどんなパラメータでどのように調整すればこうなる。

と言う事は知っていてもデザイナー側からはどう操作していいかわからない事があります。

そんな時にどんな人でもわかりやすいように値の設定やサンプル値の設定等が出来たら便利ですよね?

エディターを拡張する事でインスペクタの表示を変えたり、わかりやすく設定値を変更出来るようにしておくわけです。

うーん・・・・わたくしの場合は一人で開発するからエディター拡張の利点をそれほど感じる事はないですし説得力ないですね・・・・・(-_-)

とりあえず便利なんですよー (;一_一)

スポンサーリンク

エディター拡張の仕方

エディタ拡張は作成したスクリプト、例えばキャラクター用の操作スクリプトを使って拡張しインスペクタの表示を変更します。

その為、まずは拡張したいスクリプトを1つ用意する必要があります。

拡張される側のスクリプトの用意

今回拡張するスクリプトはMyDataという名前のスクリプトにします。

通常通りMonoBehaviourクラスを継承してMyDataクラスを作成しています。

キャラクターのHPや攻撃力等のフィールド、またエディター拡張のテスト用にスタイルや文字列を用意しています。

実用的なスクリプトではありませんが、キャラクターの持っているパラメータはこんな感じのデータを持っている事が多いと思います。

MyDataスクリプトは

Editor拡張される側のスクリプトの置き場

↑のような階層に作成しました。

スクリプトを拡張する側のスクリプトの作成

サブタイトルが解り辛くなってますが・・・、さきほど作成したMyDataを拡張するスクリプトの作成の事ですね。

まず最初に注意しなければいけないのは拡張する側のスクリプトはEditorフォルダ内に置かなければいけないという事です。

逆に拡張される側のスクリプト(MyData)はEditorフォルダ内に置いてはいけません。

EditorフォルダはAssetsの直下に作成した方がいいかもしれません。

それ以外の場所、例えばAssets/MyScript/Editorの中に拡張する側のスクリプトを置いて試したんですが動作がうまくいかなかったので・・・・。

なのでまずはAssets/Editorフォルダを作成します。

今回は拡張する側のスクリプト名をMyDataEditorという名前で作り、Assets/Editor/EditorTestフォルダの中に入れます。

拡張する側のスクリプトはEditorフォルダの中に作ったフォルダ内においても大丈夫です。

Editorを拡張する側のスクリプトの置き場

↑のような感じになります。

これでエディター拡張をする準備が整いました。

エディターを拡張する為の記述

それではMyDataEditorスクリプトに処理を記述していきましょう。

まずはエディターを拡張する時に必要になる記述です。

クラスはEditorクラスを継承して作成します。

また、クラスにはCustomEditorアトリビュートを取りつけ、引数に拡張される側のスクリプト名をtypeofで指定します。

こうする事でMyDataスクリプトを拡張してMyDataEditorクラスを作成出来ます。

MyDataのデータを取得する

MyDataEditorはMyDataスクリプトの拡張をするクラスなのでMyDataで宣言されているhpやattackPowerなどのデータにアクセスする手段が必要です。

SerializedProperty

その為に使用するのがSerializedPropertyです。

Editorクラスで定義されているserializedObjectのFindPropertyを利用して取得する事が出来ます。

↑のようにプロパティを取得し、その値を表示する事が出来ます。

OnInspectorGUIメソッドについては後述します。

target

もうひとつの方法がEditorクラスで宣言されているtargetを使用する事です。

targetには拡張される側のクラス(MyData)オブジェクトが入っているのでそれをMyDataにキャストし使用します。

OnInspectorGUIメソッド内に記述します。

targetで得たMyDataクラスからspeedの値を取得し、インスペクタに表示しそれを再度myData.speedに入れています。

OnInspectorGUI

インスペクタのデータを更新すると呼ばれるのがOnInspectorGUIメソッドです。

その為エディターを拡張する側のスクリプトでインスペクタの値を表示するにはOnInspectorGUIメソッドを記述しその中に処理を書きます。

このOnInspectorGUIメソッドはoverrideをします。

シリアライズオブジェクトのデータを使う場合はserializedObject.UpdateとserializedObject.ApplyModifiedPropertiesを使います。

↑のようにシリアライズデータを挟む形で記述します。

インスペクタにボタンを表示

インスペクタにボタンを表示するにはGUILayout.Buttonを使用します。

↑のように記述するとインスペクタにボタンが表示されボタンを押した時の処理はif文内に書きます。

インスペクタにボタンを表示

EditorGUILayout.IntSlider

EditorGUILayout.IntSliderを使用するとint型のスライダーを作成する事が出来ます。

↑のようにhpシリアライズデータを0~100の間で変更するスライダーを作成する事が出来ます。

インスペクタにスライダーを表示

EditorGUI.ProgressBar

EditorGUI.ProgressBarでプログレスバーを表示する事が出来ます。

指定した領域(Rect)でhpの値のパーセンテージをプログレスバーで表示しています。

インスペクタにプログレスバーを表示

EditorGUILayout.MinMaxSlider

EditorGUILayout.MinMaxSliderを使用すると最小値と最大値をバーでつないだスライダーを使用する事が出来ます。

最初の引数が現在の最小値、2番目の引数が現在の最大値、3番目の引数が設定出来る最小値、4番目の引数が設定出来る最大値

インスペクタに最小最大値を設定出来るスライダーの表示

EditorGUILayout.BeginHorizontal

インスペクタで並びを整列する時に使用します。

EditorGUILayout.BeginHorizontalが横の始まりでEditorGUILayout.EndHorizontalが終わりです。

縦の整列をしたい時はHorizontalの部分をVerticalに変更します。

エディターの変更値を保存

Unityのゲームでデータを保存するにはPlayerPrefsを使用すると出来ますが、

Unityでゲームデータのセーブ・ロードを行う方法
Unityのゲームで進行具合やキャラクターのステータスをデータとして保存しておき、それらのデータを読みだして続きから再開するというのは必須の機能になっています。 その為に今回はゲームデータのセーブとロードが出来るようにしてみたいと思います。

エディターの設定等を保存したい時はEditorPrefsを使用する事で出来ます。

使い方はPlayerPrefsと同じように使う事が出来ます。

とするとTESTというEditorPrefsデータが作成され、値がtrueに設定されます。

EditorPrefsデータの保存先はMacOSとWindowsでは異なります。

https://docs.unity3d.com/jp/current/ScriptReference/EditorPrefs.html

EditorGUILayout.HelpBox

EditorGUILayout.HelpBoxを使うとインスペクタにヘルプボックスを表示する事が出来ます。

↑のように使用します。

メッセージの種類を指定する事でヘルプの内容なのか注意喚起なのかといったメッセージの種類を設定出来ます。

CanEditMultipleObjectsアトリビュート

エディター拡張をする側のスクリプトにCanEditMultipleObjectsアトリビュートを付けるとされる側のスクリプト(MyData)を複数のゲームオブジェクトに設定し、

それらのゲームオブジェクトを複数選択した時に共通のインスペクタの項目を一緒に変更する事が出来ます。

このアトリビュートが設定されていない場合は同じスクリプトが設定されていても同時に値を変更する事は出来ません。

CanEditMultipleObjectsを付けていない時

↑がCanEditMultipleObjectsアトリビュートをクラスに付けていない時の表示です。

同じMyDataスクリプトを取りつけた複数のクラスを選択しても値の変更が出来ません。

CanEditMultipleObjectsを付けた時

↑がCanEditMultipleObjectsを付けた場合です。

MyDataスクリプトを取りつけた複数のゲームオブジェクトを選択しインスペクタで項目の値を変更すると選択したゲームオブジェクト全てのMyDataの項目値が変更されます。

DrawDefaultInspector

インスペクタに元々ある値はそのまま使いたい場合はSerializedPropertyやtargetから値を取得しなくても、

DrawDefaultInspectorメソッドを呼び出せば拡張される側のMyDataのフィールドがそのままインスペクタに表示されます。

インスペクタをカスタマイズするサンプル

簡単なカスタマイズの説明だけになりましたが、MyDataEditorスクリプトにサンプルを記述し確認してみます。

SerializedPropertyを使ったやり方とtargetを使ったやり方でインスペクタに値を表示しています。

MinMaxSliderの最小値と最大値では最小値をspeed、最大値をdashSpeedに設定するようにしています。

でインスペクタで設定したStyleによってラベルを表示しています。

ラベルはテクスチャやテキストが設定出来ます。

テクスチャとテキストを両方使いたい場合はGUIContentを作成すると一緒に使えます。

とします。

他にはインスペクタにボタンを作成し、インスペクタの値をリセットしたり、EditorPrefsにTESTというデータを操作する処理です。

サンプルが出来たので確認してみましょう。

↑のようになりました。

通常のインスペクタとはずいぶん変わりましたね。

EditorGUILayout.LabelField (“TesT”, myData.style, GUILayout.MaxWidth (500));

の行でエラーが発生する時があります(横幅が足りない時?)。

今回紹介したエディターのカスタマイズ方法の他にも出来る事はあるので確認してみてください。

参考サイト

Property Drawers & Custom Inspectors

Editor Scripting Intro

スポンサーリンク

記事をシェアして頂ける方はこちら

フォローして頂くとやる気が出ます