Unity の Reorderable のエディタ拡張を作る
Unity 2020.2 の Inspector では、配列は並び替えが可能な Reorderable
なものに変わりました。
自作クラスのデフォルト表示
下記のように [Serializable]
を指定した自作クラスについても、手軽に Reorderable
なGUIを Inspector で確認できます。便利ですね。
using System; using UnityEngine; [Serializable] public class TestObject { public GameObject Prefab; public Vector3 Position; public Vector3 Rotate; } public class TestComponent : MonoBehaviour { public TestObject[] TestObjects = {new TestObject(),}; }
けれど、ちょっと見づらいですね。イマイチポイントを挙げると以下のとおり。
- 一覧性に欠けている
- Foldoutを閉じた状態 :
Element 1
といった連番のラベル情報しか表示されない- → 配列の中身を識別できる固有の情報を表示したい
- Foldoutを開いた状態 :
- → インデントを用いて、データのまとまりを表現したい
- Foldoutを閉じた状態 :
自作クラスのエディタ拡張
ということで、エディタ拡張を書いて解決をしてみます。
EditorGUILayout
は使えないので、 EditorGUI
で Rect をしっかり指定します。
using System; using UnityEngine; using UnityEditor; [Serializable] public class TestObject { public GameObject Prefab; public Vector3 Position; public Vector3 Rotate; } public class TestComponent : MonoBehaviour { public TestObject[] TestObjects = {new TestObject(),}; } [CustomPropertyDrawer(typeof(TestObject))] public class TestObjectDrawer : PropertyDrawer { private static float GetPropertyHeight(SerializedProperty property = null) { var height = property == null ? EditorGUIUtility.singleLineHeight : EditorGUI.GetPropertyHeight(property, true); return height + EditorGUIUtility.standardVerticalSpacing; } private static bool FoldoutField(ref Rect rect, SerializedProperty property, string label, string propertyName) { var prop = property.FindPropertyRelative(propertyName); prop.isExpanded = EditorGUI.Foldout(rect, prop.isExpanded, GUIContent.none); EditorGUI.PropertyField(rect, prop, new GUIContent(label)); rect.y += GetPropertyHeight(prop); return prop.isExpanded; } private static void Field(ref Rect rect, SerializedProperty property, string label, string propertyName) { var prop = property.FindPropertyRelative(propertyName); EditorGUI.PropertyField(rect, prop, new GUIContent(label), true); rect.y += GetPropertyHeight(prop); } public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { position.height = EditorGUIUtility.singleLineHeight; if (FoldoutField(ref position, property, "Prefab", "Prefab")) { EditorGUI.indentLevel++; Field(ref position, property, "Position", "Position"); Field(ref position, property, "Rotate", "Rotate"); EditorGUI.indentLevel--; } } public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { var enableSkinName = property.FindPropertyRelative("Prefab"); var height = GetPropertyHeight(enableSkinName); if (enableSkinName.isExpanded) { height += GetPropertyHeight(property.FindPropertyRelative("Position")); height += GetPropertyHeight(property.FindPropertyRelative("Rotate")); } return height; } }
これでようやく使い物になりそうな見た目になりましたね。 ちょっとした気遣いで、UnityEditor上の作業はすごく楽になるので、「ゲームの内容には関係ないし・・」とか思わず、ちょいちょいっと書いていきましょい