Inspector面板扩展(EditorGUI、EditorGUILayout、GUI、GUILayout)

41 篇文章 2 订阅

Inspector面板扩展(EditorGUI、EditorGUILayout、GUI、GUILayout)

前言

最近,一个项目涉及到比较多的模块,每个模块又有不同的情况和动作,有公用的,也有特例。所以为了方便修改(直接在面板上选择)并且一目了然,我使用了编辑器,画出我自己需要的Inspector面板,显示我需要的信息。同时,为了以后查看,特地来做整理。

这些信息是根据脚本中声明的public可序列化变量而来的,要美观并实用的显示这些信息,让面板更具可操作性,我们就需要使用到EditorGUI、EditorGUILayout、GUI、GUILayout等来进行规划和布局。

系统简介

转载:

1、系统简介具体的介绍见:https://blog.csdn.net/qq992817263/article/details/79292426/

2、GUILayoutEditorGUILayout 控件整理见:https://blog.csdn.net/qq_38275140/article/details/84778344

3「Unity3D」(10)自定义属性面板Inspector详解   From:scottcgi

简介:

1、GUI系统

这是运用最广泛的GUI系统,所属命名空间UnityEngine,用其绘制的所有控件不带有自动布局效果,需要手动指定每个控件的绘制位置和大小,自适应性较弱,但开发自由度较高

注意:GUI系统可以在发布后使用,也可以在编辑器中使用。

2、GUILayout系统

带自动布局的GUI系统,所属命名空间UnityEngine,用其绘制的所有控件都带有自动布局效果,自适应性较强,但开发自由度较低

注意:GUILayout系统可以在发布后使用,也可以在编辑器中使用。

3、EditorGUI系统

适用于编辑器的GUI系统,所属命名空间UnityEditor,用其绘制的所有控件不带有布局效果,需要手动指定每个控件的绘制位置和大小,跟GUI系统的差别是其拥有部分编辑器专用控件,且其只能运行在编辑器内,自适应性较弱,但开发自由度较高

注意:EditorGUI系统不可以在发布后使用,只能在编辑器中使用。

4、EditorGUILayout系统

带自动布局的EditorGUI系统,所属命名空间UnityEditor,用其绘制的所有控件都带有自动布局效果,跟GUILayout系统的差别是其拥有部分编辑器专用控件,且其只能运行在编辑器内,自适应性较强,但开发自由度较低

注意:EditorGUILayout系统不可以在发布后使用,只能在编辑器中使用。

以上四个GUI系统可以混用,EditorGUIEditorGUILayout系统中的控件多是带Field,可见其用意主要是用来展示字段的值,GUI系统由于不带布局,所以在编辑器开发中使用的较少,除非有时候需要创建高自由度的界面时会首选他,GUILayout系统开发编辑器工具是使用得最多的。

Inspector面板扩展

一、基本结构认识:

  1. 首先在Unity中的Project下建一个文件夹,命名为Editor;
  2. 新建一个C#脚本,命名为Test1Editor,放在刚刚新建的Editor文件夹下(注:Editor脚本最好都放在名为Editor的文件夹下);
  3. 新建一个文件夹,命名为Scripts,用来存放脚本;
  4. 在Scripts文件夹下新建一个C#脚本,命名为Test1。

1、绘制原有属性

using System.Collections;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;

//CustomEditor(typeof()) 用于关联要自定义的脚本
//CanEditMultipleObjects 支持多物体同时编辑
[CustomEditor(typeof(Test1)),CanEditMultipleObjects]
public class Test1Editor : Editor {


    private void OnEnable()
    {

    }
    //重写OnInspectorGUI
    public override void OnInspectorGUI()
    {
        // 绘制Test1全部原有public属性
        base.DrawDefaultInspector();
        // 后面可以自定义扩展自己的功能
    }
}

2、自定义绘制属性

(1)基本框架:

    public override void OnInspectorGUI()
    {
        serializedObject.Update();//开头,更新显示,可以不写

        /*中间,自定义绘制*/
        
        serializedObject.ApplyModifiedProperties();//结尾,应用修改,必须有,不然不能修改
    }

(2)可以选择性的绘制public属性对象:

方法一:

  1. 定义
  2. 声明,在Test1中寻找要绘制的对象属性
  3. 重写OnInspectorGUI,进行绘制

   

using System.Collections;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
[CustomEditor(typeof(Test1))]
public class Test1Editor : Editor {
    
    //定义
    static SerializedProperty vector2;

    private void OnEnable()
    {
        //声明(查找对象属性)FindProperty
        vector2 = serializedObject.FindProperty("vector2");
    }
    public override void OnInspectorGUI()
    {
        //绘制
        EditorGUILayout.PropertyField(vector2);
        //查找对象属性的属性并赋值(FindPropertyRelative)
        vector2.FindPropertyRelative("x").floatValue = 10f;

        serializedObject.ApplyModifiedProperties();
    }
}

小结: 

  1. 有两个接口用来查找已有的属性(Test1中的public属性变量),FindProperty和FindPropertyRelative。
  2. FindProperty:用来查找当前属性名对应的属性对象。
  3. FindPropertyRelative:查找属性对象的属性。

方法二:

直接定义Test1:Test1 test1 = target as Test1;

#if UNITY_EDITOR
using UnityEditor;
#endif
[CustomEditor(typeof(Test1))]
public class Test1Editor : Editor
{
    
    public override void OnInspectorGUI()
    {
        Test1 test1 = target as Test1;

        test1.vector2 = EditorGUILayout.Vector2Field("二维坐标",test1.vector2);
      
        serializedObject.ApplyModifiedProperties();
    }
}

二、绘制所用控件介绍

(一)空格的几种写法

GUILayout.Space(10);//空格,写法1(可以控制空格大小,数字越小,空格越小)

EditorGUILayout.Space();//空格,写法2

EditorGUILayout.Separator();//分隔符

(二)布局类

1、BeginFadeGroup:用来隐藏/显示在它包含的组中的内容。value则是显示内容的量,范围是0~1 。设置为0.5,就是显示50%;设置为0.85,就是显示85%。

public override void OnInspectorGUI()
{
    EditorGUILayout.BeginFadeGroup(0.5f);

    EditorGUILayout.LabelField("Inspector");
    EditorGUILayout.LabelField("Inspector");
    EditorGUILayout.LabelField("Inspector");

    EditorGUILayout.EndFadeGroup();

    serializedObject.ApplyModifiedProperties();
}

    

2、BeginHorizontal:水平布局;EndHorizontal:结束水平布局;
             BeginVertical:垂直布局;EndVertical:结束垂直布局

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("水平布局1");
        EditorGUILayout.LabelField("水平布局2");
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.Space(); 

        EditorGUILayout.BeginVertical();
        EditorGUILayout.LabelField("垂直布局1");
        EditorGUILayout.LabelField("垂直布局2");
        EditorGUILayout.EndVertical();

  

若加上"box",就会有个布局框,即:

EditorGUILayout.BeginHorizontal("box");

EditorGUILayout.EndHorizontal();

效果如下:

3、BeginScrollView:开始滚动视图;EndScrollView:结束滚动视图

test1.scrollView=EditorGUILayout.BeginScrollView(test1.scrollView, GUILayout.Width(Screen.width), GUILayout.Height(80));

EditorGUILayout.LabelField("这是ScrollView");
EditorGUILayout.LabelField("这是ScrollView");
EditorGUILayout.LabelField("这是ScrollView");
EditorGUILayout.LabelField("这是ScrollView");
EditorGUILayout.LabelField("这是ScrollView");
EditorGUILayout.LabelField("这是ScrollView");

EditorGUILayout.EndScrollView();

   

(三)Field类

1.Text:文本

  • EditorGUILayout.TextField:只能写一行
  • EditorGUILayout.TextArea:能换行写多行
  • EditorGUILayout.DelayedTextField:延时,要回车之后才提交修改
[CustomEditor(typeof(Test1)),CanEditMultipleObjects]
public class Test1Editor : Editor
{
    private string textfiled;
    private string textarea;

    static SerializedProperty DelayedTextField;

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

    public override void OnInspectorGUI()
    {
        Test1 test1 = target as Test1;

        //TextField
        test1.Textfield= EditorGUILayout.TextField("TextField",test1.Textfield);//写法一
        textfiled = EditorGUILayout.TextField("textfiled", textfiled);//写法二

        //空格
        EditorGUILayout.Space();

        //TextArea
        test1.Textarea = EditorGUILayout.TextArea(test1.Textarea);
        textarea = EditorGUILayout.TextArea(textarea);

        EditorGUILayout.Space();

        //DelayedTextField
        EditorGUILayout.DelayedTextField(DelayedTextField);

        serializedObject.ApplyModifiedProperties();
    }
}

   

2、Password:密码字段

//Passworld
test1.Password = EditorGUILayout.PasswordField("密码:", test1.Password);

  

3、数字

  1. IntField:整数字段                                 5. DelayedIntField:整数,延迟输入框
  2. FloatField:浮点数字段                         6. DelayedFloatField:浮点数,延迟输入框
  3. DoubleField:双精度浮点型字段           7. DelayedDoubleField:双精度浮点数,延迟输入框
  4. LongField:长整型字段 

     注:延迟输入框,在按下回车键或将焦点从文本字段移开之后,才返回新值

    static SerializedProperty DelayedIntField;
    static SerializedProperty DelayedFloatField;
    static double DelayedDoubleField;

    private void OnEnable()
    {
        DelayedIntField = serializedObject.FindProperty("DelayedIntField");
        DelayedFloatField = serializedObject.FindProperty("DelayedFloatField");
    }

    public override void OnInspectorGUI()
    {
        Test1 test1 = target as Test1;

        test1.intfield = EditorGUILayout.IntField("IntField", test1.intfield);
        test1.floatfield = EditorGUILayout.FloatField("FloatField", test1.floatfield);
        test1.doublefield = EditorGUILayout.DoubleField("DoubleField", test1.doublefield);
        test1.longfield = EditorGUILayout.LongField("LongField", test1.longfield);
        
        EditorGUILayout.Space();

        EditorGUILayout.DelayedIntField(DelayedIntField);
        EditorGUILayout.DelayedFloatField(DelayedFloatField);
        EditorGUILayout.DelayedDoubleField("DelayedDoubleField", DelayedDoubleField);

        serializedObject.ApplyModifiedProperties();
    }

   

4、BoundsField:边界输入框

public override void OnInspectorGUI()
{
    Test1 test1 = target as Test1;

    test1.bounds = EditorGUILayout.BoundsField("BoundsField:", test1.bounds);

    serializedObject.ApplyModifiedProperties();
}
public class Test1 : MonoBehaviour
{
    public Bounds bounds;
}

   

5、RectField:矩形字段

test1.rect= EditorGUILayout.RectField("RectField",test1.rect );

   

6.ObjectField:物体字段

public override void OnInspectorGUI()
    {
        Test1 test1 = target as Test1;

        test1.objectfield = EditorGUILayout.ObjectField("ObjectField", test1.objectfield, typeof(Object), true);

        serializedObject.ApplyModifiedProperties();
    }
public class Test1 : MonoBehaviour
{
    public Object objectfield;
}

  

 7、ColorField:颜色

test1.color = EditorGUILayout.ColorField("Color", test1.color);
public class Test1 : MonoBehaviour
{
    public Color color = Color.red;
}

   

8、CurveField:曲线

test1.curvefield = EditorGUILayout.CurveField("CurveField", test1.curvefield);
public class Test1 : MonoBehaviour
{
    public AnimationCurve curvefield = AnimationCurve.Linear(0, 0, 10, 10);
}

  

9、向量字段

  • Vector2Field:二维向量
  • Vector3Field:三维向量
  • Vector4Field:四维向量
    vector2field = EditorGUILayout.Vector2Field("Vector2Field", vector2field);
    vector3field = EditorGUILayout.Vector3Field("Vector3Field", vector3field);
    vector4field = EditorGUILayout.Vector4Field("Vector4Field", vector4field);

  

10、LayerField:层字段

//LayerField
EditorGUILayout.LayerField("LayerField",0);

  

  11、TagField:标签字段

EditorGUILayout.TagField("Tag for Objects:","这是一个Tag");

  

(四)选择开关按钮

1、Toggle 与 ToggleLeft

test1.b1 = EditorGUILayout.Toggle("b1", test1.b1);
test1.b2 = EditorGUILayout.ToggleLeft("b2", test1.b2);
public class Test1 : MonoBehaviour
{
    public bool b1, b2;
}

  

2、BeginToggleGroup:开始开关组;EndToggleGroup:结束开关组

//开始开关组
test1.b3 = EditorGUILayout.BeginToggleGroup("ToggleGroup", test1.b3);

test1.pos[0] = EditorGUILayout.Toggle("x", test1.pos[0]);
test1.pos[1] = EditorGUILayout.Toggle("y", test1.pos[1]);
test1.pos[2] = EditorGUILayout.Toggle("z", test1.pos[2]);
        
//结束开关组
EditorGUILayout.EndToggleGroup();
public class Test1 : MonoBehaviour
{
    public bool b3;
    public bool[] pos = new bool[3] { false, false, false };
}

  

(五)Slider:滑动条

  • Slider:滑动条
  • IntSlider:整数滑动条
  • MinMaxSlider: 最小最大滑动条
//滑动条
test1.sliderValue = EditorGUILayout.Slider("Slider", test1.sliderValue, 0, 1);
//整数滑动条
test1.intSliderValue = EditorGUILayout.IntSlider("IntSlider", test1.intSliderValue, 0, 10);
//最大最小滑动条
EditorGUILayout.MinMaxSlider("MinMaxSlider", ref test1.minSliderValue, ref test1.maxSliderValue, 0, 10);
public class Test1 : MonoBehaviour
{
    public float sliderValue;
    public int intSliderValue;
    public float minSliderValue, maxSliderValue;
}

   

(六)下拉列表

  •  Popup:标准弹出选择菜单
  • IntPopup:整数弹出选择菜单
  • EnumPopup:(单选)枚举弹出选择菜单
  • EnumMaskPopup:(多选)枚举弹出选择菜单
  • EnumMaskField:(多选)枚举弹出选择菜单
  • MaskField:(多选)数组弹出选择菜单
  • DropdownButton:(单选)下拉菜单
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;

[CustomEditor(typeof(Test1)), CanEditMultipleObjects]//自定义预览窗
public class Test1Editor : Editor {

    //声明

    int popupIndex;
    string[] popupArry = { "a", "b", "c" };

    static SerializedProperty choose1;

    private int maskField;

    private string DropdownButtonName= "DropdownButton";

    //定义
    private void OnEnable()
    {
        choose1 = serializedObject.FindProperty("choose1");
    }
    //规划面板
    public override void OnInspectorGUI()
    {
        Test1 test1 = target as Test1;

        //Popup
        EditorGUILayout.Popup("Popup", popupIndex, popupArry);

        //IntPopup
        test1.intPopup= EditorGUILayout.IntPopup("IntPopup",test1.intPopup, new string[] { "1", "2", "3" },new int[]{4,5,6});

        EditorGUILayout.PropertyField(choose1);//下拉列表
        //EnumPopup
        test1.choose2 = (Choose)EditorGUILayout.EnumPopup("EnumPopup", test1.choose2);
        
        //EnumMaskPopup
        test1.choose3 = (Choose)EditorGUILayout.EnumMaskPopup("EnumMaskPopup", test1.choose3);

        //EnumMaskField
        test1.choose4 = (Choose)EditorGUILayout.EnumMaskField("EnumMaskField", test1.choose4);

        //maskField
        maskField = EditorGUILayout.MaskField("MaskField", maskField, new string[] { "1", "2" });

        EditorGUILayout.Space();

        //DropdownButton
        if (EditorGUILayout.DropdownButton(new GUIContent(DropdownButtonName), FocusType.Keyboard))
        {
            string[] alls = new string[4] { "A", "B", "C", "D" };
            GenericMenu _menu = new GenericMenu();
            foreach (string item in alls)
            {
                if (string.IsNullOrEmpty(item))
                {
                    continue;
                }
                //添加菜单
                _menu.AddItem(new GUIContent(item), DropdownButtonName.Equals(item), OnValueSelected, item);
            }
            //显示菜单
            _menu.ShowAsContext();
        }

        serializedObject.ApplyModifiedProperties();
    }
    void OnValueSelected(object value)
    {
        DropdownButtonName = value.ToString();
        switch (DropdownButtonName)
        {
            case "A":
                Debug.Log("A");
                break;
            case "B":
                Debug.Log("B");
                break;
            case "C":
                Debug.Log("C");
                break;
            case "D":
                Debug.Log("D");
                break;
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public enum Choose
{
    choose1, choose2, choose3, choose4
}
public class Test1 : MonoBehaviour {

    public int intPopup;
    public Choose choose1 = Choose.choose1;
    public Choose choose2 = Choose.choose2;
    public Choose choose3;
    public Choose choose4;
}

  

(七)数组

#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;

[CustomEditor(typeof(Test1)), CanEditMultipleObjects]//自定义预览窗
public class Test1Editor : Editor {

    static SerializedProperty arry1,arry2;

    private void OnEnable()
    {
        arry1 = serializedObject.FindProperty("arry1");
        arry2 = serializedObject.FindProperty("arry2");
    }
    
    public override void OnInspectorGUI()
    {
        // 缩进一级【不然数组会顶格(左边),与上面的对不齐】
        EditorGUI.indentLevel++;
        EditorGUILayout.PropertyField(arry1, true);//要写true,不然打不开数组
        EditorGUILayout.PropertyField(arry2, true);

        serializedObject.ApplyModifiedProperties();
    }
}
    
public class Test1 : MonoBehaviour 
{
    public int[] arry1;
    public string[] arry2;
}

  

(八)Foldout:折叠框

using UnityEditor.AnimatedValues;
#if UNITY_EDITOR
using UnityEditor;
#endif

public class Test1Editor : Editor {

    private bool foldout;
    private AnimBool fadeGroup;
    
    private void OnEnable()
    {
        fadeGroup = new AnimBool(false);
        // 注册动画监听
        fadeGroup.valueChanged.AddListener(Repaint);
    }
    private void OnDisable()
    {
        // 移除动画监听
        fadeGroup.valueChanged.RemoveListener(Repaint);
    }
    public override void OnInspectorGUI()
    {
        foldout = EditorGUILayout.Foldout(foldout, "FoldOut");
        if (foldout)
        {
            EditorGUILayout.LabelField("这是一个折叠框");
            EditorGUI.indentLevel++;
            EditorGUILayout.LabelField("这是一个折叠框");
            EditorGUI.indentLevel--;
        }

        fadeGroup.target = EditorGUILayout.Foldout(fadeGroup.target, "BeginFadeGroup", true);
        if (EditorGUILayout.BeginFadeGroup(this.fadeGroup.faded))
        {
            EditorGUILayout.BoundsField("BoundsField", new Bounds());
        }
        // 动画
        EditorGUILayout.EndFadeGroup();

        serializedObject.ApplyModifiedProperties();
    }
}

  

(九)HelpBox:帮助框

public class Test1Editor : Editor {
    
    public override void OnInspectorGUI()
    {
        EditorGUILayout.HelpBox("这个没有属性", MessageType.None);
        EditorGUILayout.HelpBox("这是个错误", MessageType.Error);
        EditorGUILayout.HelpBox("这是个提示", MessageType.Info);
        EditorGUILayout.HelpBox("这是个警告", MessageType.Warning);

        serializedObject.ApplyModifiedProperties();
    }
}

   

  • 13
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值