[閱讀筆記] Unity のエディター拡張 #3

《Unity のエディター拡張》後所留下的簡單筆記,第九到十一章。 介紹了 CustomEditor,也就是最常被使用的 自訂 Inspector 操作介面,這幾個章節內容很多,我覺得介紹依舊尚淺而有些不明白。 CustomEditor 真是博大精深的領域!

第九章:CustomEditor

  • CustomEditor 是指 自訂 提供給 Component 顯示於 Inspector 與 SceneView 中的 編輯器
  • Inspector 視窗可以切換 Normal / Debug 兩個模式,分成 GUI 顯示或者只列出 Serialize Field 欄位資訊。
  • 一般應用可以利用第二章介紹的功能自訂部分 Inspector 視窗。
  • 直接實作 CustomEditor 需要繼承 Editor 類別,並使用 CustomEditor (Type) 這個 Attribute 指定想要對應的 MonoBehaviour。
    • 自訂的 GUI 需透過 override 寫於 OnInspectorGUI 及 OnSceneGUI 兩個方法中。
    • base.OnInspectorGUI () 記得於 override 後進行呼叫。
  • 作為 Editor 存取 MonoBehaviour 的 Serialize Field 參數的手段:
    • 使用 Editor.serializedObject 來存取,透過 serializedObject.FindProperty() 來取得特定欄位。
    • 直接參照 MonoBehaviour,進行操作。
  • Undo 的實作:
    • EditorGUI.BeginChangeCheck / EndChangeCheck 檢查參數是否有變化。
    • Undo.RecordObject () 進行 Undo 序列的紀錄寫入。
  • 複選多個相同 Component 的情況:
    • CanEditMultipleObjects 是允許複數編輯的 Attribute。
    • 複數編輯是對多個 serializedObject 的存取與操作。
    • Editor.targets 可以取得被複選的 Component 實體,進行複數選取時的綜合介面實作。
    • EditorGUI.showMixedValue 用於標示接下來的欄位,不同 Component 的值相異,數值顯示會以橫槓 (ー) 表示。
    • 值的寫入需要用迴圈操作。
  • 用 PropertyDrawer 實作特定類別的編輯器:
    • 需要繼承 PropertyDrawer 類別,並使用 CustomPropertyDrawer (Type) 這個 Attribute 指定想要對應的 class。
    • OnGUI (Rect position, SerializedProperty property, GUIContent label) 是實作 GUI 的指定方法。
    • 透過 property.FindPropertyRelative 可以取得對性類別的 Serialize Field 資訊。
    • GetPropertyHeight () 必須 override 並回傳自訂編輯器的高度,才能正確的在 Inspector 上繪製。
    • base.GetPropertyHeight (property, label) 可取得依照 Serialize Field 數量計算的預設高度。
  • Inspector 下方的預覽窗:
    • Editor.HasPreviewGUI () 經過 override,會在回傳 true 時顯示預覽窗。
    • Editor.GetPreviewTitle () 用於實作標題。
    • Editor.OnPreviewSettings () 用於實作右上方按鈕。
    • Editor.OnPreviewGUI (Rect r, GUIStyle background) 用於實作窗口內容。
    • 透過 PreviewRenderUtility 進行場景的取景與渲染。
    • 如果需要單一物件的預覽:
      • 使用 Object.Instantiate 生成預覽用物件。
      • 物件設定為 HideFlags.HideAndDontSave。
      • 以 Camera.PreviewCullingLayer 為 cullingMask 進行 PreviewRenderUtility 的渲染。
    • Editor.OnInteractivePreviewGUI (Rect r, GUIStyle background) 用於實作可以互動 (旋轉物件) 的預覽窗。
  • 針對 Asset (而非腳本) 也可以實作 Editor 來增加對資源的支援。

第十章:PropertyDrawer

  • PropertyDrawer 是為特定類別設計,通用於所有相關應用的 Component 上, 顯示 Serialize Field 於 Inspector。
  • PropertyDrawer 除了對應類別,也可以對應到 PropertyAttribute 的實作。
  • 如果實作的 CustomGUI 跟預設的 GUI 高度不同,則必須實作 GetPropertyHeight() 的 override,Inspector 才能正確運作。
    • base.GetPropertyHeight() 會取得預設 GUI 的高度。
  • EditorGUILayout.Knob 本來不可用於 PropertyDrawer,但本章節使用了 Reflection 強制將這個 EditorGUI 用於 PropertyDrawer 上。
  • 本章的其他範例:
    • 連結參數到同一物件其他 Component 的資訊。
    • 讓對應欄位顯示 GUI 跟數值但無法編輯。
    • 讓 enum 的 popup menu 用指定字串代替數值。
    • 實作 int,string 等變數的 popup menu。
    • url 圖片預覽。
    • 用下拉選單選擇場景名稱存入 string 變數。

第十一章:ProjectWindowUtil

  • ProjectWindowUtil 用於處理在 Project 視窗創建資源、變更名稱等動作。
  • ProjectWindowUtil.CreateAsset () 創建資源,並進入命名模式,與 AssetDatabase.CreateAsset 會直接定名不同。
    • 實際上內部呼叫了 StartNameEditingIfProjectWindowExists ()。
  • ProjectWindowUtil.StartNameEditingIfProjectWindowExists () 創建資源並進行更名動作。
    • EndNameEditAction 是更名動作需要的一個傳入參數,可用於自訂更名完畢的後續動作。
    • EndNameEditAction 需用 ScriptableObject.CreateInstance() 實體化。
  • 透過 ProjectWindowUtil 可以實作各種自訂資源的生成,並可以在命名後進行一些處理。