開發 Unity3D 時, 是否經常在訂製 Editor, 希望為其中某些 SerializedProperty 部分做自訂, 但因為一開始訂製又需要整個 component 上的所有顯示的參數也需要訂製而覺得頭痛??!
其實如果簡單的取代某幾個 property 的繪製是可行的,
只需要以下的寫法即可.
public override void OnInspectorGUI() { serializedObject.Update(); SerializedProperty iter = serializedObject.GetIterator(); iter.NextVisible(true); // enter children. EditorGUI.BeginChangeCheck(); // ---- change check [optional] do { // draw element & it's children EditorGUILayout.PropertyField(iter, includeChildren: true); } while (iter.NextVisible(false)); if (EditorGUI.EndChangeCheck()) // ---- change check [optional] serializedObject.ApplyModifiedProperties(); }
這一段的寫法其實跟原本的
base.OnInspectorGUI();
就結果上完全沒有分別… 那麼為甚麼要這樣寫呢?!
原因
- 可以保留在 Class 中宣告參數的順序
- 可以保留一些特殊 attribute 如 [Header] [Range] 等這些繪製宣告
- 可以單獨的對某個 property 進行額外加插的自訂方式 (後文述)
- 可擴充性彈性, 基類的參數中, 沒有被指定的可以隨意增減修改, 而不需要重寫 Editor.
這裡提供一些變體用法, 跟 OnEnable 配搭可以輕易的取得當下繪製的 property, 是否自己希望修改的一員, 而作出相對應的取代.
SerializedProperty propA, propB; private void OnEnable() { propA = serializedObject.FindProperty("m_A"); propB = serializedObject.FindProperty("m_B"); } public override void OnInspectorGUI() { serializedObject.Update(); SerializedProperty iter = serializedObject.GetIterator(); iter.NextVisible(true); // enter children. EditorGUI.BeginChangeCheck(); // ---- change check [optional] do { if (iter.propertyPath == propA.propertyPath) { // Special setup for A // if (Application.isPlaying) {...} else {....} } else if (iter.propertyPath == propB.propertyPath) { // Special setup for B EditorGUILayout.PropertyField(iter, includeChildren: true); EditorGUILayout.HelpBox("more info !!!", MessageType.Info); } else { // draw element & it's children EditorGUILayout.PropertyField(iter, includeChildren: true); } } while (iter.NextVisible(false)); if (EditorGUI.EndChangeCheck()) // ---- change check [optional] serializedObject.ApplyModifiedProperties(); }
期待有更多的玩法, 歡迎討論.