[Unity]客製化Inspector
設計自己的Inspector!
緣由
自從改用GameManager的GameLoop來統一控制遊戲的整體流程後,唯一讓我困擾的是他的Inspector視窗,裡面的屬性真的太長~了,每次要除錯都要找一下子,雖然各資料屬性是class所以可以摺疊,但總歸還是非常不便(如圖,很長一大串)。
Editor資料夾
要使自己的腳本是在編輯中執行而不是在遊戲中執行的話,需要在Assets根目錄下新增一個資料夾取名為Editor,經由特殊資料夾名稱,系統會將下面的腳本認定為Editor 腳本(如圖)。
腳本
匯入與繼承
如我在資料夾內的那3個腳本一樣,新增一個腳本然後取一個你想要的名字吧。
1.首先需要匯入編輯器的命名空間 UnityEditor
2.然後添加Attribute : CustomEditor,其用途是告訴編輯器,哪一個腳本是你要自訂的對象。
3.使你腳本改繼承 Editor
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
/// <summary>
/// 客製化GameManager (MainGameLoop) 的視窗
/// </summary>
[CustomEditor(typeof(MainGameLoop))]
public class GameManagerInspector : Editor
{
覆寫Inspector的GUI設計
Editor有很多功能可以覆載,我們這次只要處理Inspector,所以只要覆載OnInspectorGUI就好。
並且指定要編輯的物件 _gameLoop,這裡有一點要注意,是可以多物件編輯的,但是Editor.target只會引用第一個已編輯物件。
public class GameManagerInspector : Editor
{
public override void OnInspectorGUI()
{
MainGameLoop _gameLoop = (MainGameLoop)target;
開始Inspector內的處理吧
GameLoop內的屬性簡單介紹
提供選單列舉
/// <summary>
/// Inspector設定的頁面類型
/// </summary>
public enum SettingType
{
MainCameraProcess,
BookUI,
SoundEffect,
WarUI,
OptionPage,
SavePage
}
public SettingType MainSettingType;
屬性
[Header("BookUI的資料")]
public BookUIData MainBookUIData;
[Header("SoundEffectData的資料")]
public SoundEffectData MainSoundEffectData;
[Header("選項頁面的資料")]
public UIOptionCtrlData MainUIOptionCtrlData;
[Header("戰爭UI的資料")]
public WarUICtrlData MainWarUICtrlData;
顯示下拉清單
MainGameLoop _gameLoop = (MainGameLoop)target;
//顯示下拉是列舉清單
_gameLoop.MainSettingType =
(MainGameLoop.SettingType)EditorGUILayout.EnumPopup("頁面類型",
_gameLoop.MainSettingType);
序列化物件
屬性欄位
像是物件屬性,或是實質型別屬性(float,int...)其實有 像是EditorGUILayout.FloatField或是EditorGUILayout.ObjectField這種方法可以使用,但原本的Attribute就會消失,而在原本屬性名稱的位置則可以自由地輸入你想要的名稱。
由於要抓取自己的類別屬性,或是抓取普通的屬性,都可以使用屬性欄位PropertuField,為了方便使用,我統一都使用
EditorGUILayout.PropertyField
完成修改後,應用屬性修改ApplyModifiedProperties()很重要,不能沒有加。
另一點,"CanvasUI"是你那個屬性的名稱,也就是說,如果你的屬性是 float _value1;,那你要輸入的就是"_value1"。
true是用來確認要不要顯示內藏的值,如果沒有打true,則會再inspector顯示屬性的名稱與箭頭,但是不管打開關閉箭頭都不會有內部的值跑出來讓你設定
serializedObject.Update();
EditorGUILayout.PropertyField(serializedObject.FindProperty
("CanvasUI"), true);
serializedObject.ApplyModifiedProperties();
加入選擇
switch (_gameLoop.MainSettingType)
{
case MainGameLoop.SettingType.MainCameraProcess:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainCameraProcessData"), true);
break;
case MainGameLoop.SettingType.BookUI:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainBookUIData"), true);
break;
case MainGameLoop.SettingType.SoundEffect:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainSoundEffectData"), true);
break;
case MainGameLoop.SettingType.WarUI:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainWarUICtrlData"), true);
break;
}
完成
完成的樣子
完整程式碼
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
/// <summary>
/// 客製化GameManager (MainGameLoop) 的視窗
/// </summary>
[CustomEditor(typeof(MainGameLoop))]
public class GameManagerInspector : Editor
{
public override void OnInspectorGUI()
{
MainGameLoop _gameLoop = (MainGameLoop)target;
//顯示下拉是列舉清單
_gameLoop.MainSettingType =
(MainGameLoop.SettingType)EditorGUILayout.EnumPopup("頁面類型",
_gameLoop.MainSettingType);
serializedObject.Update();
switch (_gameLoop.MainSettingType)
{
case MainGameLoop.SettingType.MainCameraProcess:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainCameraProcessData"), true);
break;
case MainGameLoop.SettingType.BookUI:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainBookUIData"), true);
break;
case MainGameLoop.SettingType.SoundEffect:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainSoundEffectData"), true);
break;
case MainGameLoop.SettingType.WarUI:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainWarUICtrlData"), true);
break;
case MainGameLoop.SettingType.OptionPage:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainUIOptionCtrlData"), true);
break;
case MainGameLoop.SettingType.SavePage:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainUISaveCtrlData"), true);
break;
case MainGameLoop.SettingType.MissionPage:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainUIMissionCtrlData"), true);
break;
case MainGameLoop.SettingType.ItemPage:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainUIItemCtrlData"), true);
break;
case MainGameLoop.SettingType.WeaponPage:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainUIWeaponCtrlData"), true);
break;
case MainGameLoop.SettingType.WeaponProcess:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainWeaponProcessData"), true);
break;
case MainGameLoop.SettingType.MusicCtrl:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainMusicCtrlData"), true);
break;
case MainGameLoop.SettingType.PlayerCtrl:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainPlayerCtrlData"), true);
break;
case MainGameLoop.SettingType.DialogSystem:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainDialogSystemData"), true);
break;
case MainGameLoop.SettingType.PlotSystem:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainPlotData"), true);
break;
case MainGameLoop.SettingType.Training:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainTrainingData"), true);
break;
case MainGameLoop.SettingType.LoadingProcess:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainLoadingProcessData"), true);
break;
case MainGameLoop.SettingType.StoreSystem:
EditorGUILayout.PropertyField(serializedObject.FindProperty
("MainStoreData"), true);
break;
}
EditorGUILayout.PropertyField(serializedObject.FindProperty
("PlayerObject"), true);
EditorGUILayout.PropertyField(serializedObject.FindProperty
("GameBlack"), true);
EditorGUILayout.PropertyField(serializedObject.FindProperty
("CanvasUI"), true);
serializedObject.ApplyModifiedProperties();
}
}
蠻實用的
回覆刪除