1. 程式人生 > >Unity Editor 基礎篇(二):自定義 Inspector 面板

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來執行時禁用操作) 

這裡寫圖片描述