LucifeP(ルシフェP)の日記

Unityでゲームつくっている人です。

【Unity】インスペクターに変数の検索窓を追加するエディタ拡張

Unityのインスペクターに検索窓を追加するエディタ拡張を作成しました。
変数をたくさん持つScriptableObjectから必要な変数を探すのに便利です。



1. スクリプト

検索窓を追加するエディタ拡張スクリプトです。

実際に使用する際は[CustomEditor(typeof(GameData))]GameDataを任意のクラス名に置き換えてください。
また、ビルド時のエラーや容量増加を防ぐためにEditorフォルダ下に配置してください。

using UnityEngine;
using UnityEditor;

namespace Sakineko
{
    [CustomEditor(typeof(GameData))]
    public classGameDataEditor : Editor
    {
        private string search = "";
        private bool clearClicked;   // 検索窓をクリア
        private bool isReturnFocus;  // 少し遅らせてフォーカスを検索窓に戻す

        public override void OnInspectorGUI()
        {
            serializedObject.Update();

            using (new EditorGUILayout.HorizontalScope())
            {
                EditorGUILayout.LabelField("Search");

                // アイコン
                var image = EditorGUIUtility.IconContent("Search On Icon").image;
                EditorGUILayout.LabelField(new GUIContent(image), GUILayout.Height(16), GUILayout.Width(16));

                //フォーカス戻すためコントロールに名前付け
                GUI.SetNextControlName("Search");
                search = EditorGUILayout.TextField(search);

                // フォーカスを検索窓に戻す
                // (1)フォーカスを外す (2)フォーカスを戻す で2回更新する必要があるので戻す処理を遅らせる
                if (isReturnFocus)
                {
                    GUI.FocusControl("Search");
                    isReturnFocus = false;
                }
                if (clearClicked)
                {
                    isReturnFocus = true;
                }

                // Clearボタン
                clearClicked = GUILayout.Button("Clear");
                if (clearClicked)
                {
                    search = "";

                    //フォーカスを外さないと入力が残ったように見える
                    GUI.FocusControl("");
                }
            }

            EditorGUILayout.Space();

            //検索なし
            if (search == "")
            {
                base.OnInspectorGUI();
            }
            //検索あり
            else
            {
                var iter = serializedObject.GetIterator();

                iter.NextVisible(true);
                using (new EditorGUI.DisabledScope(true))
                {
                    EditorGUILayout.PropertyField(iter, true);
                }

                while (iter.NextVisible(true))
                {
                    // 大文字・小文字を区別しない
                    if (!iter.name.ToLower().Contains(search))
                    {
                        continue;
                    }

                    EditorGUILayout.PropertyField(iter, true);
                }
            }

            serializedObject.ApplyModifiedProperties();
        }
    }
}


2. 使い方

以下のようにGameDataというScriptableObjectを継承したクラスがあった場合を想定します。

using UnityEngine;

namespace Sakineko
{
    [CreateAssetMenu(fileName = "GameDataSO", menuName = "ScriptableObjects/GameDataSO")]
    public class GameData : ScriptableObject
    {
        public int a;
        public int b;
        public int c;
        public int d;
        public int e;
    }
}


一番上に検索窓が追加されています。

検索対象の文字列を含む変数のみがインスペクター上に表示されます。