Unity Editor 基礎篇(二):自定義 Inspector 面板
自定義Inspector屬性面板
EditorGUILayout 編輯器介面佈局 這是一個編輯器類,如果想使用它你需要把它放到工程目錄下的Assets/Editor資料夾下。編輯器類在UnityEditor名稱空間下。所以當使用C#指令碼時,你需要在指令碼前面加上 “using UnityEditor”引用。
接下來開始製作的我們自己的 Inpector,對於自定義 Inpector 面板可參考EditorGUILayout的API:
開始一個可以被隱藏/顯示的組,並且這個轉換將會被啟用。 | |
用一個開關啟動一個垂直的組,使所有的控制元件同時啟用或禁用。 | |
製作一個用於編輯動畫曲線的領域。 | |
製作一個按鈕,對滑鼠做出反應,顯示你自己的下拉內容。 | |
結束一個scrollview,開始呼叫BeginScrollView。 | |
當單擊時,顯示一個帶有列舉型別值的選項的選單。值為0的選項“沒有”,而值0(即所有位元組)的選項總是顯示在選單的頂部。值0和0的名稱可以通過在enum型別中定義這些值而被過度使用 | |
建立一個enum彈出選擇欄位。 | |
為輸入浮動值建立一個文字欄位。 | |
在它的左邊用一個摺疊箭頭做一個標籤。 | |
向用戶提供一個有訊息的幫助框。 | |
為輸入整數製作一個文字框。 | |
建立一個整數彈出選擇欄位。 | |
製作一個滑動條,使用者可以拖動來改變一個最小值和最大值之間的整數值。 | |
做一個標籤欄位。(用於顯示只讀資訊。) | |
為輸入長整數建立一個文字欄位。 | |
製作一個特殊的滑塊,使用者可以使用它來指定最小值和最大值之間的範圍。 | |
Popup | 建立一個通用的彈出選擇欄位。 |
建立一個X、Y、W和H欄位來輸入一個Rect。 | |
做一個X,Y,W&H場,進入一個重新著色。 | |
建立一個可選擇的標籤欄位。(用於顯示可以複製貼上的只讀資訊)。 | |
製作一個滑動條,使用者可以拖動來改變一個最小值和最大值之間的值。 | |
Space |
在前面的控制元件和下面的控制元件之間留出一個小空間。 |
建立一個切換區域,其中的開關在左邊,標籤立即在它的右邊。 | |
製作一個X&Y欄位,用於輸入向量2。 | |
建立一個X&Y整數字段來輸入Vector2Int。 | |
製作一個X、Y&Z欄位來輸入一個向量。 | |
輸入一個X、Y&Z整數字段來輸入一個Vector3Int。 | |
做一個X、Y、Z&W欄位,輸入一個向量圖。 |
最終效果:
準備工作: 在Scripts資料夾裡建立一個新C#指令碼,命名”Player”,然後新增程式碼:
public class Player : MonoBehaviour {
public int id;
public string playerName;
public string backStory;
public float health;
public float damage;
public float weaponDamage1, weaponDamage2;
public string shoeName;
public int shoeSize;
public string shoeType;
void Start()
{
health = 50;
}
}
Player 類記錄了 Player 的一些基礎資訊,例如:ID、名字、背景故事、生命值、傷害等等。
常用的自定義Inspector介面佈局屬性:
現在在Editor資料夾中建立C#指令碼:
using System.Collections;
using UnityEngine;
using UnityEditor;
//CustomEditor(typeof()) 用於關聯你要自定義的指令碼
[CustomEditor(typeof(Player))]
//必須要讓該類繼承自Editor,且不需要匯入UnityEditor程式集
public class PlayerInspector : Editor {
Player player;
bool showWeapons;
void OnEnable()
{
//獲取當前編輯自定義Inspector的物件
player = (Player)target;
}
//執行這一個函式來一個自定義檢視面板
public override void OnInspectorGUI()
{
//設定整個介面是以垂直方向來佈局
EditorGUILayout.BeginVertical();
//空兩行
EditorGUILayout.Space();
EditorGUILayout.Space();
//繪製palyer的基本資訊
EditorGUILayout.LabelField("Base Info");
player.id = EditorGUILayout.IntField("Player ID",player.id);
player.playerName = EditorGUILayout.TextField("PlayerName",player.playerName);
//空三行
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.Space();
//繪製Player的背景故事
EditorGUILayout.LabelField("Back Story");
player.backStory = EditorGUILayout.TextArea(player.backStory,GUILayout.MinHeight(100));
//空三行
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.Space();
//使用滑塊繪製 Player 生命值
player.health = EditorGUILayout.Slider("Health",player.health,0,100);
//根據生命值設定生命條的背景顏色
if(player.health<20){
GUI.color = Color.red;
}
else if(player.health>80){
GUI.color = Color.green;
}
else
{
GUI.color = Color.gray;
}
//指定生命值的寬高
Rect progressRect = GUILayoutUtility.GetRect(50,50);
//繪製生命條
EditorGUI.ProgressBar(progressRect,player.health/100.0f,"Health");
//用此處理,以防上面的顏色變化會影響到下面的顏色變化
GUI.color = Color.white;
//空三行
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.Space();
//使用滑塊繪製傷害值
player.damage = EditorGUILayout.Slider("Damage",player.damage,0,20);
//根據傷害值的大小設定顯示的型別和提示語
if(player.damage<10){
EditorGUILayout.HelpBox("傷害太低了吧!!", MessageType.Error);
}
else if(player.damage>15){
EditorGUILayout.HelpBox("傷害有點高啊!!", MessageType.Warning);
}
else{
EditorGUILayout.HelpBox("傷害適中!!", MessageType.Info);
}
//空三行
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.Space();
//設定內容摺疊
showWeapons=EditorGUILayout.Foldout(showWeapons,"Weapons");
if(showWeapons){
player.weaponDamage1=EditorGUILayout.FloatField("Weapon 1 Damage",player.weaponDamage1);
player.weaponDamage2=EditorGUILayout.FloatField("Weapon 2 Damage",player.weaponDamage2);
}
//空三行
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.Space();
//繪製鞋子資訊
EditorGUILayout.LabelField("Shoe");
//以水平方向繪製
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Name",GUILayout.MaxWidth(50));
player.shoeName=EditorGUILayout.TextField(player.shoeName);
EditorGUILayout.LabelField("Size",GUILayout.MaxWidth(50));
player.shoeSize=EditorGUILayout.IntField(player.shoeSize);
EditorGUILayout.LabelField("Type",GUILayout.MaxWidth(50));
player.shoeType=EditorGUILayout.TextField(player.shoeType);
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
}
}
Okey,接下來一一分析一下,雖然已經上了備註。
1.Vertical-垂直佈局 預設的介面佈局就是垂直佈局,但是為了節目效果,我們還是把它寫上比較好,設定元素為垂直佈局需使用這對兄弟來宣告:
EditorGUILayout.BeginVertical();
EditorGUILayout.EndVertical();
在這對兄弟裡面做的佈局都是以垂直方向來排列的。
如上圖所示,整個頁面元素都是以垂直方向來佈局的。
2.Horizontal-水平佈局
設定元素為水平佈局需使用這對兄弟來宣告:
EditorGUILayout.BeginHorizontal();
EditorGUILayout.EndHorizontal();
在這對兄弟裡面做的佈局都是以水平方向來排列的。
由於我們在上圖圈選的地方使用了 Horizontal 這對兄弟,因此在這對兄弟裡的元素全是以水平方向排列。
3.空行 使用 EditorGUILayout.Space() 可在兩個元素之間空出一行。
4.繪製各種型別欄位 繪製欄位用到以下幾個方法:
EditorGUILayout.LabelField()標籤欄位
EditorGUILayout.IntField() 整數字段
EditorGUILayout.FloatField() 浮點數字段
EditorGUILayout.TextField() 文字欄位
EditorGUILayout.Vector2Field() 二維向量欄位
EditorGUILayout.Vector3Field() 三維向量欄位
EditorGUILayout.Vector4Field() 四維向量欄位
EditorGUILayout.ColorField() 顏色欄位
它們的規律就是方法名都是以 Field 結尾,大夥們可以根據繪製的型別選擇相對應的方法。 一般括號裡面的引數,第一個為繪製該欄位的名字(string 型別),第二個為繪製該欄位的值,如下所示:
1 為標籤欄位 2 為整形欄位 3 為文字欄位 4.為文字區域
5.滑塊、進度條 1.滑塊:EditorGUILayout.Slider() 製作一個滑動條使用者可以拖動來改變值,在最小和最大值之間
static float Slider(float value,float leftValue,float rightValue,GUILayoutOptionp[] params options)
static float Slider(string label,float value,float leftValue,float rightValue,GUILayoutOptionp[] params options)
static float Slider(GUIContent label,float value,float leftValue,float rightValue,GUILayoutOptionp[] params options)
引數: label: 條目前面的可選標籤 value:編輯的值 leftValue、rightValue:滑動條最左右的值 options:指定額外佈局屬性的可選列表。這裡傳遞任意值,將覆蓋樣式定義的設定。
EditorGUILayout.Slider()用於繪製一個滑塊,從上可知:
第一個引數是滑塊的名字 第二個引數是滑塊要改變的值 第三和第四個引數是滑塊的範圍 效果如下圖所示:
2/ 進度條:EditorGUI.ProgressBar() 製作一個進度條
static void ProgressBar(Rect position,float value,string text)
引數: Position:螢幕上的矩形區域,用來總的這兩者控制 value:顯示的值
EditorGUI.ProgressBar()用於繪製一個進度條,從上可知:
第一個引數是設定進度條的大小,型別是一個 Rect。 第二個引數是設定顯示的值, 第三個引數是設定進度條的名字
提示: 1.第一個引數,我們使用了 GUILayoutUtility.GetRect() 工具類的 GetRect()方法返回一個設定好的矩形框,在案例裡我們設定了一個 50*50 大小的矩形框。
2.第二個引數,我們使用 player.health / 100.0f。那是因為進度條的最大值為1,如果不除100的話,當滑塊的值為1時,進度條便填滿了,因此我們想讓值與進度條的比例同步,那就除100吧(語文不好,不知道解釋得如何)。
效果圖:
6.幫助框 幫助框:EditorGUILayout.HelpBox()
EditorGUILayout.HelpBox()用於繪製一個盒子(也可以看作矩形框),然後再盒子的裡面顯示提示資訊,從上圖可知:
第一個引數是傳入提示資訊 第二個引數是提示資訊的型別
效果圖:
6.灰色地帶(禁用區域) EditorGUI.BeginDisabledGroup建立一組可以禁用(可見不可操作 )的繪製顯示,為true時禁用 EditorGUILayout.BeginToggleGroup開始帶有開關按鈕的一個垂直組,在這裡立即啟用或禁用控制元件。 如:
private SerializedProperty m_EditorResourceMode = null;
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
m_EditorResourceMode.boolValue = EditorGUILayout.BeginToggleGroup("Editor Resource Mode", m_EditorResourceMode.boolValue);
{
EditorGUILayout.HelpBox("Editor resource mode option is only for editor mode. Game Framework will use editor resource files, which you should validate first.", MessageType.Warning);
//EditorGUILayout.PropertyField(m_EditorLanguage);
EditorGUILayout.HelpBox("Editor language option is only use for localization test in editor mode.", MessageType.Info);
}
EditorGUILayout.EndToggleGroup();
}
效果: 開關組控制
禁用組繪製控制:(使用EditorApplication.isPlayingOrWillChangePlaymode來執行時禁用操作)