エディタ拡張をしていると、クラスや配列を折りたたむ時のアレを実装することがありますよね。
これは Foldout というようですが、これの実装ですごい回り道をしてしまったのでメモ的に書いておきます。
以下のようなクラスがあるとします。
FoldoutTest.cs
using UnityEngine;
public class FoldoutTest : MonoBehaviour {
[System.Serializable]
private class SampleClass
{
[SerializeField] string hoge;
[SerializeField] int fuga;
}
[SerializeField] SampleClass sampleClass;
}
このコンポーネントを適当なオブジェクトに張り付けてインスペクターに表示させると以下のようになりますね。
このSample Class
という部分の表示ですが、EditorGUILayout.PropertyField()
を使えば簡単にできます。
using UnityEditor;
[CustomEditor(typeof(FoldoutTest))]
public class FoldoutTestEditor : Editor {
SerializedProperty sampleClass;
void OnEnable()
{
sampleClass = serializedObject.FindProperty("sampleClass");
}
public override void OnInspectorGUI()
{
EditorGUILayout.PropertyField(sampleClass);
}
}
簡単ですね。ちゃんとクリックすれば開いたり閉じたりといった動作をしてくれます。
あとはクラス内の要素も描画して、ついでに先頭に編集不可能なスクリプトのプロパティフィールドも表示します。
using UnityEditor;
[CustomEditor(typeof(FoldoutTest))]
public class FoldoutTestEditor : Editor {
SerializedProperty script;
SerializedProperty sampleClass;
SerializedProperty hoge, fuga;
void OnEnable()
{
script = serializedObject.FindProperty("m_Script");
sampleClass = serializedObject.FindProperty("sampleClass");
hoge = sampleClass.FindPropertyRelative("hoge");
fuga = sampleClass.FindPropertyRelative("fuga");
}
public override void OnInspectorGUI()
{
// スクリプト名を表示する. 編集はできないようにする.
EditorGUI.BeginDisabledGroup(true);
EditorGUILayout.PropertyField(script);
EditorGUI.EndDisabledGroup();
EditorGUILayout.PropertyField(sampleClass);
if(sampleClass.isExpanded)
{
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(hoge);
EditorGUILayout.PropertyField(fuga);
EditorGUI.indentLevel--;
}
}
}
できました!クラスの開閉状態はSerializedProperty.isExpanded
で調べられます。
こうすれば、拡張するクラス側に#UNITY_EDITOR
で囲った開閉管理用変数を用意してFoldoutの描画や範囲内のクリック判定を自前でしたり、クラスが配列だった場合に増減の瞬間開閉管理用変数を操作する苦労とかしなくてすみますね!
ぼくも2度としたくないので次からはこの方法を取るようにします。