自定義Inspector面板
Attribute自定義Inspector
實現下面的組件,體驗幾個Attribute的作用:
public class EditorTest : MonoBehaviour
{
[Header("屬性標題")]
[Tooltip("This is a property.")]
public int property1;
[Space(1f)]
[Tooltip("This is another property.")]
public int property2;
[Foldout("Group")]
public int a;
[Foldout("Group")]
public int b;
[Foldout("Group")]
public int c;
}
Header(string header)屬性可以在Inspector中增加一個粗體的標題。
Space(float hight)屬性可以在Inspector中增加一段間隔。
Tooltip(string tooltip)屬性使你在Inspector面板中將鼠標浮動在屬性上時顯示一個文字提示。
Foldout(string foldout)屬性可以在Inspector面板中渲染摺疊欄,參數名稱相同的屬性放置在同一個摺疊欄中。
組件的Editor腳本
以封裝一個邏輯判斷系統爲例展示使用Editor腳本修改組件在Inspector面板的顯示的方法。
在Project面板的根目錄下創建一個名爲"Editor"的文件夾,在其下新建腳本,命名爲LogicalSystemEditor。同樣在根目錄下創建一個名爲"Scripts"的文件夾,在其下新建腳本,命名爲LogicalSystem。打開LogicalSystemEditor,修改類型定義如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;c
using UnityEngine.UI;
[CustomEditor(typeof(LogicalSystem))]
public class LogicalSystemEditor : Editor
{
public override void OnInspectorGUI()
{
}
}
使用幾個類來封裝邏輯系統,下面的腳本使用了ScriptableObject,將來會着重學習,感興趣的可以提前瞭解:
[CreateAssetMenu]
[System.Serializable]
public class LogicalSystem : ScriptableObject
{
public List<OrStatement> orStatement = new List<OrStatement>();
public uint orStatementLength;
public bool matchStatement
{
get
{
foreach(OrStatement statement in orStatement)
{
if(statement.matchStatement) return true;
}
return false;
}
}
}
[System.Serializable]
public class OrStatement
{
public List<AndStatement> andStatement = new List<AndStatement>();
public uint andStatementLength;
public bool matchStatement
{
get
{
foreach(AndStatement statement in andStatement)
{
if(!statement.matchStatement) return false;
}
return true;
}
}
}
[System.Serializable]
public class AndStatement
{
public LogicalCondition condition;
public bool matchStatement()
{
switch(condition)
{
//未完成,請自行補充
}
}
}
[System.Serializable]
public enum LogicalCondition
{
//未完成,請自行補充
}
修改LogicalSystemEditor如下:
public class LogicalSystemEditor : Editor
{
public override void OnInspectorGUI()
{
LogicalSystem s = (LogicalSystem)target;
s.orStatementLength = (uint)EditorGUILayout.IntField("Conditions:", (int)s.orStatementLenth);
if (s.orStatementLength <= 0) s.orStatementLength = 1;
for (; s.orStatementLength > s.orStatement.Count;)
{
s.orStatement.Add(new OrStatement());
}
for (int i = 0; i < s.orStatementLength; i++)
{
OrStatement orBlock = s.orStatement[i];
orBlock.andStatementLength = (uint)EditorGUILayout.IntField(" Or " + i, (int)orBlock.andStatementLength);
if (orBlock.andStatementLength <= 0) orBlock.andStatementLength = 1;
for (; orBlock.andStatementLength > orBlock.andStatement.Count;)
{
orBlock.andStatement.Add(new AndStatement());
}
for(int j = 0; j < orBlock.andStatementLength; j++)
{
AndStatement statement = orBlock.andStatement[j];
statement.condition = (EffectConditionType)EditorGUILayout.EnumPopup(" And " + j, statement.condition);
switch(statement.condition)
{
}
}
}
}
}
在Project面板右鍵創建一個新的LogicalSystem,即可在Inspector面板觀察到自定義的結果。
LogicalSystem s = (LogicalSystem)target;
在Editor腳本中,調用target屬性可以獲得我們試圖修改的那個對象,在這裏我們還需要將target拆箱,於是使用強制類型轉換,並將其保存到一個局部遍歷s中,這是爲了後面書寫的方便。
s.orStatementLength = (uint)EditorGUILayout.IntField("Conditions:", (int)s.orStatementLenth);
在此我們使用了EditorGUILayout.IntField()函數,這個函數可以在Inspector面板中繪製一個輸入整數的輸入框。函數的第一個參數用於修改這個輸入框前的文字信息,第二個參數是輸入框中值的來源,而返回值是修改後的結果。由於我們想讓這個輸入框的輸入和輸出都指向同一個屬性,所以使用了兩次s.orStatementLength。由於這個屬性是一個uint,而函數的參數和返回值類型都是int,所以使用了兩次強制類型轉換。
statement.condition = (EffectConditionType)EditorGUILayout.EnumPopup(" And " + j, statement.condition);
在此我們又用了一個EditorGUILayout.EnumPopup函數,這個函數的作用是繪製一個Enum的下拉選框。函數的第一個參數是下拉選框前的文字信息,第二個參數是值的來源,返回值是修改後的結果。同上,我們使用了兩次一樣的屬性。由於函數返回類型爲Object,我們使用了一次強制類型轉換。
public static Rect EditorGUILayout.BeginHorizontal(); public static void EditorGUILayout.EndHorizontal(); public static Rect EditorGUILayout.BeginVertical(); public static void EditorGUILayout.EndVertical();
可以控制屬性的排版,在Begin和End中間渲染的其它Inspector組件會呈豎直或水平排版。
public static Vector2 EditorGUILayout.BeginScrollView(Vector2 scrollPosition, bool alwaysShowHorizontal, bool alwaysShowVertical); public static void EditorGUILayout.EndScrollView();
渲染一個可以滾動的子面板,通過在其中鑲嵌BeginHorizontal()等函數可以更好的自定義面板。
public static Color EditorGUILayout.ColorField(string label, Color value);
渲染一個顏色條。參數和返回值都需要填同一個對象,label指輸入框前的文字信息。
public static double EditorGUILayout.DoubleField(string label, double value); public static float EditorGUILayout.FloatField(string label, float value); public static int EditorGUILayout.FloatField(string label, int value);
渲染一個可以輸入數值的文本框。
public static float EditorGUILayout.Slider(string label, float value, float leftValue, float rightValue); public static int EditorGUILayout.IntSlider(string label, int value, int leftValue, int rightValue);
渲染一個滑動條,可以輸入或拖動數值。
public static Enum EditorGUILayout.EnumPopup(string label, Enum selected);
渲染一個可以選擇Enum的下拉選框。注意,Enum必須具有System.Serializable標記。
public static Enum EditorGUILayout.EnumFlagsField(string label, Enum enumValue);
渲染一個可以多選的下拉選框。適用這個方法的Enum需要特別構建:
[System.Serializable] enum ExampleFlagsEnum { None = 0, // Custom name for "Nothing" option A = 1 << 0, B = 1 << 1, AB = A | B, // Combination of two flags C = 1 << 2, All = ~0, // Custom name for "Everything" option }
在ExampleFlagsEnum的渲染中,Enum的值被以位的方式解讀,選中的每個值會連續做按位或運算,並將結果輸出。注意,Enum必須具有System.Serializable標記。
public static void EditorGUILayout.Space();
渲染一段空行。
public static void EditorGUILayout.LabelField(string label);
渲染一段不能修改的標題字符。
public static string EditorGUILayout.TextField(string label, string text); public static string EditorGUILayout.TextArea(string text);
渲染一個可供輸入的文本框。Area是多行的,Field是單行的。
public static Vector2 EditorGUILayout.Vector2Field(string label, Vector2 value); public static Vector3 EditorGUILayout.Vector3Field(string label, Vector3 value); public static Vector4 EditorGUILayout.Vector3Field(string label, Vector4 value); public static Vector2Int EditorGUILayout.Vector2IntField(string label, Vector2Int value); public static Vector3Int EditorGUILayout.Vector3IntField(string label, Vector3Int value); public static Vector4Int EditorGUILayout.Vector4IntField(string label, Vector4Int value);
渲染用於輸入向量的組合輸入框。
public static bool EditorGUILayout.Toggle(string label, bool value);
渲染一個返回布爾類型的勾選框。
public static Object EditorGUILayout.ObjectField(string label, Object obj, Type objType, bool allowSceneObjects);
渲染一個可以拖入任何類型的框,尤其適用於拖入ScriptableObject或MonoBehaviour。
這個方法還可以用於渲染拖入圖片的框體,如下列代碼:
target.icon = EditorGUILayout.ObjectField("Icon", target.icon, typeof(Sprite), true) as Sprite;