Unity 編輯器擴(kuò)展二 Editor 自定義Inspector面板

OnInspectorGUI()是Unity的Editor類里的相關(guān)函數(shù),通過(guò)對(duì)該方法的重寫馍迄,可以自定義對(duì)Inspector面板的繪制檀葛。


image.png
//Test1.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Test1 : MonoBehaviour
{
    public Text Text1;
    public bool myBool;
    public string myString;
}

//Test1Editor.cs
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(Test1))]
public class Test1Editor : Editor
{
    public override void OnInspectorGUI()
    {
        Test1 test = (Test1)target;
        test.myBool = EditorGUILayout.Toggle("是否選中", test.myBool);
        test.myString = EditorGUILayout.TextField("輸入文本", test.myString);
    }
}

這里要先創(chuàng)建Test1腳本,再創(chuàng)建Test1Editor港准,否則引用會(huì)報(bào)錯(cuò)。

看一下前后對(duì)比圖

如圖對(duì)比咧欣,重寫了OnInspectorGUI之后浅缸,Inspector面板發(fā)生變化。因?yàn)闆](méi)有處理Text1魄咕,重寫之后已經(jīng)無(wú)法設(shè)置衩椒。

以下參考
【Unity 編輯器】擴(kuò)展總結(jié)三:自定義Inspector面板
Unity Editor 基礎(chǔ)篇(二):自定義 Inspector 面板
Unity檢視面板重構(gòu)(OnInspectorGUI重寫)
unity編輯器擴(kuò)展#1 自定義窗口、面板哮兰、和屬性

一毛萌、兩種方式

創(chuàng)建目標(biāo)類,掛載在場(chǎng)景對(duì)象中

using UnityEngine;

public enum Course
{
    Chinese,
    Mathematics, 
    English 
}

public class InspectorExample : MonoBehaviour
{
    public int intValue;
    public float floatValue;
    public string stringValue;
    public bool boolValue;
    public Vector3  vector3Value; 
    public Course enumValue = Course.Chinese;
    public Color colorValue = Color.white;
    public Texture textureValue;
}
1.繪制方式一
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(InspectorExample))]
public class InspectorExampleEditor : Editor
{
    //target指該編輯器類繪制的目標(biāo)類奠蹬,需要將它強(qiáng)轉(zhuǎn)為目標(biāo)類
    private InspectorExample _target { get { return target as InspectorExample; } }

    //GUI重新繪制
    public override void OnInspectorGUI()
    {
        //EditorGUILayout.LabelField("IntValue",_target.intValue.ToString(),EditorStyles.boldLabel);
        //_target.intValue = EditorGUILayout.IntSlider(new GUIContent("Slider"),_target.intValue, 0, 10);
        //_target.floatValue = EditorGUILayout.Slider(new GUIContent("FloatValue"), _target.floatValue, 0, 10);
        _target.intValue = EditorGUILayout.IntField("IntValue", _target.intValue);
        _target.floatValue = EditorGUILayout.FloatField("FloatValue", _target.floatValue);
        _target.stringValue = EditorGUILayout.TextField("StringValue", _target.stringValue);
        _target.boolValue = EditorGUILayout.Toggle("BoolValue", _target.boolValue);
        _target.vector3Value = EditorGUILayout.Vector3Field("Vector3Value", _target.vector3Value);
        _target.enumValue = (Course)EditorGUILayout.EnumPopup("EnumValue", (Course)_target.enumValue);
        _target.colorValue = EditorGUILayout.ColorField(new GUIContent("ColorValue"), _target.colorValue);
        _target.textureValue = (Texture)EditorGUILayout.ObjectField(
        "TextureValue", _target.textureValue, typeof(Texture), true);
    }
}
2.繪制方式二
using UnityEditor;

[CustomEditor(typeof(InspectorExample))]
public class InspectorExampleEditor : Editor
{
    //定義序列化屬性
    private SerializedProperty intValue;
    private SerializedProperty floatValue;
    private SerializedProperty stringValue;
    private SerializedProperty boolValue;
    private SerializedProperty vector3Value;
    private SerializedProperty enumValue;
    private SerializedProperty colorValue;
    private SerializedProperty textureValue;

    private void OnEnable()
    {
        //通過(guò)名字查找被序列化屬性朝聋。
        intValue = serializedObject.FindProperty("intValue");
        floatValue = serializedObject.FindProperty("floatValue");
        stringValue = serializedObject.FindProperty("stringValue");
        boolValue = serializedObject.FindProperty("boolValue");
        vector3Value = serializedObject.FindProperty("vector3Value");
        enumValue = serializedObject.FindProperty("enumValue");
        colorValue = serializedObject.FindProperty("colorValue");
        textureValue = serializedObject.FindProperty("textureValue");
    }

    public override void OnInspectorGUI()
    {
        //表示更新序列化物體
        serializedObject.Update();
        EditorGUILayout.PropertyField(intValue);
        EditorGUILayout.PropertyField(floatValue);
        EditorGUILayout.PropertyField(stringValue);
        EditorGUILayout.PropertyField(boolValue);
        EditorGUILayout.PropertyField(vector3Value);
        EditorGUILayout.PropertyField(enumValue);
        EditorGUILayout.PropertyField(colorValue);
        EditorGUILayout.PropertyField(textureValue);
        //應(yīng)用修改的屬性值,不加的話囤躁,Inspector面板的值修改不了
        serializedObject.ApplyModifiedProperties();
    }
}

P.S. 第二種繪制方式相較于第一種冀痕,顯示的效果是差不多的。雖然腳本內(nèi)容多了一點(diǎn)狸演,但是方式比較簡(jiǎn)單言蛇。不用根據(jù)每個(gè)變量的數(shù)據(jù)類型選擇相對(duì)應(yīng)的屬性API繪制。

3.使用方式二改造之前的Test1Editor
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(Test1))]
public class Test1Editor : Editor
{
    //定義序列化屬性
    private SerializedProperty Text1;
    private SerializedProperty myBool;
    private SerializedProperty myString;

    private void OnEnable()
    {
        //通過(guò)名字查找被序列化屬性宵距。
        Text1 = serializedObject.FindProperty("Text1");
        myBool = serializedObject.FindProperty("myBool");
        myString = serializedObject.FindProperty("myString");
        Debug.Log("test 1 editor enable");
    }

    public override void OnInspectorGUI()
    {
        //Test1 test = (Test1)target;
        //test.myBool = EditorGUILayout.Toggle("是否選中", test.myBool);
        //test.myString = EditorGUILayout.TextField("輸入文本", test.myString);

        //表示更新序列化物體
        serializedObject.Update();
        EditorGUILayout.PropertyField(Text1);
        //EditorGUILayout.PropertyField(myBool);
        EditorGUILayout.PropertyField(myBool, new GUIContent("是否選中"));
        EditorGUILayout.PropertyField(myString);
        //應(yīng)用修改的屬性值腊尚,不加的話,Inspector面板的值修改不了
        serializedObject.ApplyModifiedProperties();
    }
}

這里PropertyField如果需要修改顯示屬性满哪,可以參考Unity屬性窗口編輯器婿斥,改為EditorGUILayout.PropertyField(myBool, new GUIContent("是否選中"));

4.布局
        serializedObject.Update();
        EditorGUILayout.BeginHorizontal("box");
        EditorGUILayout.PropertyField(Text1);
        //EditorGUILayout.PropertyField(myBool);
        EditorGUILayout.PropertyField(myBool, new GUIContent("是否選中"));
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.PropertyField(myString);
image.png

水平和垂直布局,注意這是一個(gè)方法對(duì)哨鸭,Begin和End不能少

 EditorGUILayout.BeginVertical("box");
 //TODO
 EditorGUILayout.EndVertical();

 EditorGUILayout.BeginHorizontal("box");
 //TODO
 EditorGUILayout.EndHorizontal();
二民宿、數(shù)組或list集合的顯示方式

參考【Unity 編輯器】擴(kuò)展總結(jié)七:數(shù)組或list集合的顯示方式

using System.Collections.Generic;
using UnityEngine;

public class InspectorExample : MonoBehaviour
{
    //序列化
    [SerializeField] 
    public int[] intArray;
    [SerializeField]
    public List<string> stringList;
}

using UnityEditor;

[CustomEditor(typeof(InspectorExample))]
public class InspectorExampleEditor : Editor
{
    private SerializedProperty intArray;
    private SerializedProperty stringList;

    private void OnEnable()
    {
        intArray = serializedObject.FindProperty("intArray");
        stringList = serializedObject.FindProperty("stringList");
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        EditorGUILayout.PropertyField(intArray,true);
        EditorGUILayout.PropertyField(stringList, true);
        serializedObject.ApplyModifiedProperties();
    }
}
三、ReorderableList實(shí)現(xiàn)可排序列表

參考【Unity 編輯器】擴(kuò)展總結(jié)七:數(shù)組或list集合的顯示方式像鸡,原文中還有拓展:ReorderableList添加下拉菜單活鹰,這里不再轉(zhuǎn)載。

using System.Collections.Generic;
using UnityEngine;

public class TargetExample : MonoBehaviour
{
   [SerializeField]
   public List<string> stringArray;
}
using UnityEngine;
using UnityEditor;
using UnityEditorInternal;

[CustomEditor(typeof(TargetExample))]
public class TargetExampleEditor : Editor
{
   private ReorderableList _stringArray;

   private void OnEnable()
   {
       _stringArray = new ReorderableList(serializedObject, serializedObject.FindProperty("stringArray")
           , true, true, true, true);

       //自定義列表名稱
       _stringArray.drawHeaderCallback = (Rect rect) =>
       {
           GUI.Label(rect, "StringArray");
       };

       //自定義繪制列表元素
       _stringArray.drawElementCallback = (Rect rect,int index,bool selected,bool focused) =>
       {
           //根據(jù)index獲取對(duì)應(yīng)元素
           SerializedProperty item = _stringArray.serializedProperty.GetArrayElementAtIndex(index);
           rect.height = EditorGUIUtility.singleLineHeight;
           rect.y += 2;
           EditorGUI.PropertyField(rect, item, new GUIContent("Element "+index));
       };

       //當(dāng)添加新元素時(shí)的回調(diào)函數(shù),自定義新元素的值
       _stringArray.onAddCallback = (ReorderableList list) =>
       {
           if (list.serializedProperty != null)
           {
               list.serializedProperty.arraySize++;
               list.index = list.serializedProperty.arraySize - 1;
               SerializedProperty item = list.serializedProperty.GetArrayElementAtIndex(list.index);
               item.stringValue = "Default Value";
           }
           else
           {
               ReorderableList.defaultBehaviours.DoAddButton(list);
           }
       };

       //當(dāng)刪除元素時(shí)候的回調(diào)函數(shù)志群,實(shí)現(xiàn)刪除元素時(shí)着绷,有提示框跳出
       _stringArray.onRemoveCallback = (ReorderableList list) =>
       {
           if (EditorUtility.DisplayDialog("Warnning","Do you want to remove this element?","Remove","Cancel"))
           {
               ReorderableList.defaultBehaviours.DoRemoveButton(list);
           }
       };
   }

   public override void OnInspectorGUI()
   {
       serializedObject.Update();
       //自動(dòng)布局繪制列表
       _stringArray.DoLayoutList();
       serializedObject.ApplyModifiedProperties();
   }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市锌云,隨后出現(xiàn)的幾起案子荠医,更是在濱河造成了極大的恐慌,老刑警劉巖桑涎,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件子漩,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡石洗,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門紧显,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)讲衫,“玉大人,你說(shuō)我怎么就攤上這事孵班∩媸蓿” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵篙程,是天一觀的道長(zhǎng)枷畏。 經(jīng)常有香客問(wèn)我,道長(zhǎng)虱饿,這世上最難降的妖魔是什么拥诡? 我笑而不...
    開封第一講書人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮氮发,結(jié)果婚禮上渴肉,老公的妹妹穿的比我還像新娘。我一直安慰自己爽冕,他們只是感情好仇祭,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著颈畸,像睡著了一般乌奇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上眯娱,一...
    開封第一講書人閱讀 49,950評(píng)論 1 291
  • 那天礁苗,我揣著相機(jī)與錄音,去河邊找鬼困乒。 笑死寂屏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播迁霎,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼吱抚,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了考廉?” 一聲冷哼從身側(cè)響起秘豹,我...
    開封第一講書人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎昌粤,沒(méi)想到半個(gè)月后既绕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡涮坐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年凄贩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片袱讹。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡疲扎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出捷雕,到底是詐尸還是另有隱情椒丧,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布救巷,位于F島的核電站壶熏,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏浦译。R本人自食惡果不足惜棒假,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望精盅。 院中可真熱鬧淆衷,春花似錦、人聲如沸渤弛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)她肯。三九已至佳头,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間晴氨,已是汗流浹背康嘉。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留籽前,地道東北人亭珍。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓敷钾,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親肄梨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子阻荒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容