UnityでEditor拡張を作る方法

1. はじめに

こんにちは。
株式会社アドグローブ ゲーム事業部エンジニアの乗附(のつけ)です。

Unityプロジェクトでの開発経験がある方なら一度は目にしたことがあると思われるEditor拡張。
本記事では「Editor拡張を行ったことがない」という人のために、導入部分について書こうと思います。

■エディタ拡張とは

エディタ拡張は既存で用意されているEditor機能以外を専用のC#スクリプトを書くことで追加していくことです。

■なぜエディタ拡張をするのか

用途はさまざまですが基本的には「開発効率を上げる」ことが目的となります。
例えばAssetのImport設定を変えたい場合、それが何百個もあった場合は時間がかかり、ヒューマンエラーも発生しやすくなるというリスクがあります。
しかし、拡張機能として一括で行えるようにおけば時間もかからず、設定ミスも起こりづらい、何かあった場合もその部分だけ修正すれば済むことになります。

2. 拡張機能作成の準備

Editor拡張はUnityEditorのAPIを利用します。
しかしUnityEditorの機能はビルドに含めることができませんので、Assets以下に「Editor」という名前のフォルダを追加し、その中に.csファイルを追加する必要があります。
※Unityにおける特殊なフォルダに関しては下記URLをご参照ください
docs.unity3d.com

3. 拡張機能の実装

Editor拡張で行えることはさまざまですが、本記事では下記の3つについて順に説明します。

  • EditorWindowの生成
    GUIを利用した値の表示や、特定の操作を行えます。
    Editorタブから表示する形式が一番よく見かける形式かと思います。
  • 右クリックメニューへの追加
    Editor上で右クリックを押すことで開けるメニューに、特定の関数を呼び出すメニューを追加します。 選択しているAssetに対する操作や、Assetの追加などに利用できます。
  • InspectorViewの表示内容編集
    InspectorViewの内容をカスタマイズし、従来では表示されない形式にすることができます。
    データ管理やデバッグ機能の追加などに利用できます。
    ※元々表示されていた内容を表示しないようにすることもできるので、作成する際は注意が必要です。
■EditorWindowの生成

EditorWindowを生成するには、EditorWindowを継承したクラスから「GetWindow」を呼び出すことで生成できます。

public class SampleEditorWindow : EditorWindow
{
    private void Open()
    {
        SampleEditorWindow window = GetWindow<SampleEditorWindow>();
    }
}

しかし、このままではEditor上での操作から呼び出せませんので、MenuItemというAttributeを追加します。
MenuItemは引数で指定したパスに新しいメニューを追加し、設定した関数を呼び出すことができます。

public class SampleEditorWindow : EditorWindow
{
    [MenuItem("Sample/Open SampleWindow")]
    private void Open()
    {
        SampleEditorWindow window = GetWindow<SampleEditorWindow>();
    }
}

このようにすることで下図のようにメニューに追加することができ、関数を呼び出すことができます。

あとはこのスクリプトファイル内にOnGUI関数を用意し、レイアウトや処理を用意していくことで自由に機能を追加していくことができます。

■右クリックメニューへの追加

続いて右クリックメニューへの追加方法を説明します。 こちらは先ほど紹介したMenuItemで指定しているパスのルート部分を以下のものに指定することで追加できます。

*ProjectViewのAssets以下で開くメニューに追加

パスの頭に「Assets」を指定する。

[MenuItem("Assets/Sample")]

*HierarcyViewで開くメニューに追加

パスの頭に「GameObject」を指定する。

[MenuItem("GameObject/Sample")]

*Add Componentから開くメニューに追加

パスの頭に「Component」を指定する。

[MenuItem("Component/Sample")]

上記以外にも、以下のものがありますが長くなるので割愛します。
用途に応じて利用してみてください。

【MenuItem("CONTEXT/[コンポーネント名]/[メニュー名]")]】
特定のコンポーネントで右クリックをした際のメニューに追加

【ContextMemu』
追加したコンポーネントのInspectorView右クリック時のメニューに追加

【ContextMenuItem】
設定したInspector表示の変数右クリック時のメニューに追加

■InspectorViewの表示内容編集

Inspectorの表示内容を編集するにはCustomEditorを利用します。

[CustomEditor(typeof(SampleClass))]
public class SampleCustomInspector : Editor
{
    public override void OnInspectorGUI()
    {
    }
}

しかし、これだけでは何も表示されなくなってしまいます。
もともと表示されていた内容を表示したい場合はbaseクラスのOnInspectorGUIを呼びましょう。

[CustomEditor(typeof(SampleClass))]
public class SampleCustomInspector : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
    }
}

あとはGUIを利用して自由にカスタマイズしていくだけになります。

拡張機能の実装の紹介は以上となります。

4. 終わりに

UnityEditorの拡張自体は非常に簡単に行えます。
しかし、大事なのは追加した機能とそれにかかる工数です。
いくら便利でもそれにかかる工数が見合わなければ効率がよくないですし、機能をたくさん追加しても使わなければ意味がありません。
この辺りは、追加する機能は本当に必要なのかなど慎重に吟味する必要があります。
これからEditor拡張を始めるという方は、今自分がしている作業がEditor拡張で賄えないか?追加した機能をベースに使いまわせないか?を考えてから実装していくといいかもしれません。

今回の記事でEditor拡張を始めるきっかけとなれれば幸いです。
最後までお読みいただきありがとうございます。