みんな大好き、Unity のエディタ拡張の基礎。
Unity 2018 以降、エディタ拡張まわりについても UI 変革のロードマップが示されていますが、ここから数年ぐらいは、まだまだ既存 UI に則ったエディタ拡張が重宝されるのではないかと思われます。
ここでは、エディタ拡張を始めるにあたって、まずおさえておきたいクラスや関数について、簡単にまとめていきます。
試行環境:Unity 2017.4.4f1
目次
新規ウインドウでエディタ拡張を始める際のクラス
新しいツール等を作成する際は、基本的にこれで良いかと。
using UnityEngine;
using UnityEditor;
public class EditorWindowSample : EditorWindow
{
[MenuItem("Tools/SomeToolWindow")] // MenuItem() の中が, Unity Editor 上部ツールバーから開くための場所になります.
private static void Open()
{
GetWindow<EditorWindowSample>("タブに表示したいタイトル");
}
// Awake などは, Open した時に走る.
private void Awake()
{
// ロードすべきファイルなどがあれば, ココで実行すると良い.
}
}
↓こんな感じで選択できるようになっているので…。
↓こんな感じにウインドウが開きます。
参考に、EditorWindow クラス公式ドキュメントへのリンクはこちら。
EditorWindow – Unity スクリプトリファレンス
既存クラスのインスペクタ拡張を始める際のクラス
既存クラスのインスペクタで、使い勝手にどうしても不便が出る場合に使用します。
[CustomEditor(typeof(AnyClassName), true)] // AnyClassName は, 拡張対象とするクラス. 第二引数の bool は, 子へ継承するか否か.
public class AnyClassNameInspector : Editor
{
// 変更を加えたい元クラスの変数に, 対応させたプロパティを持たせる.
SerializedProperty mHpProperty;
SerializedProperty mAttackProperty;
SerializedProperty mDefenceProperty;
void OnEnable()
{
// 元クラスの変数と対応させる.
mHpProperty= serializedObject.FindProperty("mHp");
mAttackProperty= serializedObject.FindProperty("mAttack");
mDefenceProperty= serializedObject.FindProperty("mDefence");
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI(); // 元々のインスペクタ内容も表示させる場合に記述.
EditorGUILayout.Space();
EditorGUILayout.LabelField("↓ 『HP』『攻撃力』『守備力』を, こちらで指定してください.");
EditorGUILayout.IntField(HP, mHpProperty.intValue);
EditorGUILayout.IntField(攻撃力, mAttackProperty.intValue);
EditorGUILayout.IntField(守備力, mDefenceProperty.intValue);
}
}
このサンプルクラスの場合、base.OnInspectorGUI() は不要そう。
普通に変数をいじる分には SerializeField を使えば良い話なので、この拡張は主に「インスペクタを編集する人が別にいて、その人に内容をもう少しわかりやすく伝えたい」場合に使用されると思います。
たとえば…
- enum ポップアップの表示を、編集者にわかりやすいように、別のテキスト群から表示させる(enum では『ITEM_01』となっているところを『薬草』と表示させる)
- 編集者は『攻撃力』や『守備力』の数値を直接いじらず、武器と防具の組み合わせだけを選択し、その結果の『攻撃力』や『守備力』を自動計算して表示する
などの用途が考えられるかと思います。
こちらも参考の、公式ドキュメントリンク。
Editor – Unity スクリプトリファレンス
Project ビューでの右クリックにコマンドを追加する
関数に [MenuItem(“Assets/~”)] を追加すると、上部メニューバーの『Assets』にコマンドが追加されるとともに、「Project ビューでの右クリック」の一覧にも同様にコマンドが追加されます。
複数選択による一括処理も可能なので、一定の規則に基づいてファイル名を一括変更したい場合や、特定の拡張子のファイルを Hierarchy に Instantiate する、さらにそれを Prefab 形式に変換して保存する、といった使い方が出来ると便利です。
[MenuItem("Assets/Convert/FbxToPrefab")]
public static void ConvertFbxToPrefab()
{
// コマンド選択時の実行処理を書く.
// 右クリック時に選択していたファイルの情報を得たい場合は, こんな感じ.
foreach (Object obj in Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets))
{
// 例えば, 拡張子 .fbx のものだけ拾ってきて, Instantiate.
string file_path = AssetDatabase.GetAssetPath(obj);
if (file_path.Contains(".fbx") == false)
{
continue;
}
GameObject game_object = GameObject.Instantiate(obj) as GameObject;
// 頭に pre_ を付けて, Assets/Resources/Prefabs/HogeHoge 以下に Prefab として保存し直す.
string output_path = "Assets/Resources/Prefabs/HogeHoge/pre_" + obj.name + ".prefab";
PrefabUtility.CreatePrefab(output_path, game_object);
// Hierarchy に Instantiate したものは消しておく.
Editor.DestroyImmediate(game_object);
}
}
内部処理をさらに追加することで、単純な Prefab への変換だけでなく、例えば「このカテゴリのモデルは、一律でこの位置に、特定のエフェクトをぶら下げている」といった流れを入れつつ変換することも可能です。
Hierarchy ビューの右クリックにコマンドを追加する
Project ビューの時と同様に、関数に [MenuItem(“GameObject/~”)] を追加すると、上部メニューバーの『GameObject』にコマンドが追加されるとともに、「Hierarchy ビューでの右クリック」の一覧にも同様にコマンドが追加されます。
こちらは便利に使える機会は多くないかも知れませんが、Prefab を何度も Scene 上に呼び出したい時などに有効かも知れません。
[MenuItem("GameObject/Prefab/MapChip")]
public static void InstantiateMapChip()
{
// ここに処理を書いていく.
}
ボタン生成
原則として、エディタ GUI 内容の編集を行う内容は、private void OnGUI() の中に処理を書く必要があります。
private void OnGUI()
{
if (GUILayout.Button("ボタンタイトル", GUILayout.Width(128), GUILayout.Height(32))) // ボタンの大きさを Width と Height を指定.
{
Debug.Log("ボタンが押されましたよ.");
}
}
Width や Height 以外にも、オプション指定できる項目はいろいろあります。
GUILayout.Button – Unity スクリプトリファレンス
オプションで特にピクセル指定などを行わないままだと、横いっぱいにボタンが広がります。
文字に良い感じに合わせたい場合は、GUILayout.ExpandWidth(false) などを指定しましょう。
GUILayout.ExpandWidth – Unity スクリプトリファレンス
enum ポップアップ
public class EditorWindowSample : EditorWindow
{
enum ENUM_SAMPLE
{
NONE = -1, // 無効値.
ITEM_01,
ITEM_02,
ITEM_03,
MAX
}
ENUM_SAMPLE mEnumSample;
// 中略.
private void OnGUI()
{
mEnumSample = (ENUM_SAMPLE)EditorGUILayout.EnumPopup("所持アイテムを選んでね", mEnumSample, GUILayout.Width(256));
}
}
基本的な書き方は string や int を編集する際と同じですが、キャストが必要な点が特徴的なので、要注意です。
↓表示はこんな感じ。
EnumPopup の公式ドキュメントはこちら。
EditorGUILayout.EnumPopup – Unity スクリプトリファレンス
何か思いついたら追加していきます。
© Unity Technologies Japan/UCL