一、前言

在开发中,常常会遇到要使用OnGUI的地方。

也会遇到GUI.XXXGUILayout.XXX类似的代码,那么他们之间有什么不同呢。

IMGUI、GUI、GUILayout、EditorGUI、EditorGUILayout、OnGUI这些类之间又有什么关系呢。

这篇文章就带大家好好的整理一下这方面的内容。

首先,放一张脉络图。

unity 区域划分_unity

大图,可放大查看。

看着这张图,是不是感觉有些不知道从哪里开始看起好呢,接下来就来分析一下如何查看。

二、IMGUI

2-1、IMGUI简介

首先,我们要了解一下Unity的UI系统,Unity中有很多的UI系统。

比如IMGUIUIElementUGUINGUIFGUIUIWeigdents

  • IMGUI:用于Editor模式模式渲染UI或者运行时渲染UI。
  • UIElement(UIToolkit):可用于发布运行时和Editor模式模式渲染UI,兼顾Editor和Runtime界面,Unity最近主推的UI系统,希望逐步取代现有的UGUI系统,主要使用.uxml和.uss完成布局和样式。
  • UGUI:运行时渲染UI,主流UI系统。
  • NGUI:运行时渲染UI,曾经主流UI系统,现在已很少使用。
  • FGUI:运行时渲染UI,独立的UI编辑器,且对美术、策划都友好。

这篇文章主要侧重于IMGUI系统的讲解,GUI、GUILayout、EditorGUI、EditorGUILayout都属于Editor模式渲染或者运行时渲染UI的方案。

IMGUI也叫GUI,它是即时模式(Immediate)图形界面,IMGUI是一个代码驱动的GUI系统,不会保存UI控件上的任何信息,没有状态的概念,会重复的绘制所有的控件和状态信息,也就是OnGUI方法,每一帧都是一个全新的开始。

IMGUI是一个代码驱动的GUI系统,主要用作于程序员制作工具使用,也常用于游戏内调试代码,为脚本创建自定义检视面板,创建编辑器窗口和拓展Unity编辑器。

2-2、IMGUI实现方式

Unity提供了四个GUI类来实现IMGUI系统,分别是:

  • GUI
  • GUILayout
  • EditorGUI
  • EditorGUILayout

EditorGUIEditorGUILayout主要提供Unity的编辑器扩展的API。

GUIGUILayout主要用于游戏运行运行时的API。

接下来,我们就分别介绍一下GUI、GUILayout、EditorGUIEditor、GUILayout类。

2-3、GUI类

2-3-1、简介

GUI是Unity 的基础的IMGUI类,用于代码创建UI、位置、大小,提供了各种类型的控件,比如标签、按钮、滑动条等、

使用这个类,需要手动指定控件的位置和大小,也就是Rect,使用字符串和Textrue2D来定义控件的内容。

支持编辑器和运行时。

2-3-2、静态变量

属性

介绍

backgroundColor

用于GUI渲染的所有背景元素的全局着色颜色。

changed

如果任何控件更改了输入数据的值,则返回true。

color

对GUI应用全局色调。色调会影响背景和文本颜色。

contentColor

为GUI渲染的所有文本着色。

depth

当前正在执行的GUI的层级深度。

enable

是否启用GUI

matrix

GUI变换矩阵

skin

要使用的全局皮肤

tooltip

鼠标指针当前悬停在其上或具有键盘焦点的控件工具。

2-3-3、静态函数

属性

介绍

BeginGroup

开始一个组。必须与 EndGroup 调用配对使用。

BeginScrollView

在 GUI 内开始一个滚动视图。

Box

在 GUI 层上创建一个框。

BringWindowToBack

将特定窗口放置到该浮动窗口的后方。

BringWindowToFront

将特定窗口放置到该浮动窗口的前方。

Button

创建一个单击按钮。当用户点击该按钮时,立即执行一些操作。

DragWindow

使窗口可被拖动。

DrawTexture

在一个矩形内绘制纹理。

DrawTextureWithTexCoords

使用给定的纹理坐标在矩形内绘制纹理。

EndGroup

结束组。

EndScrollView

结束使用 BeginScrollView 调用开始的滚动视图。

FocusControl

将键盘焦点移动到某个命名控件。

FocusWindow

使某个窗口成为激活窗口。

GetNameOfFocusedControl

获取具有焦点的命名控件的名称。

HorizontalScrollbar

创建一个水平滚动条。滚动条是用于滚动文档的控件。大多数情况下,您需要的可能是滚动视图。

HorizontalSlider

用户可以拖动的水平滑动条,用于在最小值和最大值之间更改某值。

Label

在屏幕上创建一个文本或纹理标签。

ModalWindow

显示一个模态窗口。

PasswordField

创建一个可让用户输入密码的文本字段。

RepeatButton

创建一个只要用户按住就一直处于激活状态的按钮。

ScrollTo

滚动包含的所有滚动视图,让它们尝试使 position 可见。

SelectionGrid

创建一个按钮网格。

SetNextControlName

设置下一个控件的名称。

TextArea

创建一个可供用户编辑字符串的多行文本区域。

TextField

创建一个可供用户编辑字符串的单行文本字段。

Toggle

创建一个打开/关闭的开关按钮。

Toolbar

创建一个工具栏。

UnfocusWindow

从所有窗口移除焦点。

VerticalScrollbar

创建一个垂直滚动条。滚动条是用于滚动文档的控件。大多数情况下,您需要的可能是滚动视图。

VerticalSlider

用户可以拖动的垂直滑动条,用于在最小值和最大值之间更改某值。

Window

创建一个弹出窗口。

2-3-4、GUI类控件演示
2-3-4-1、Label标签

标签是非交互式的,只能显示,不能交互,不能单击。

运行时示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestOnGUI : MonoBehaviour
{
    void OnGUI()
    {
        GUI.Label(new Rect(20, 20, 100, 50), "Label");
    }
}

效果图:

unity 区域划分_游戏引擎_02


编辑器示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private void OnGUI()
    {
        GUI.Label(new Rect(20, 20, 100, 50), "Label");
    }
}

代码需要放到Editor文件夹,然后在菜单栏点击TestGUI→OnGUI:

unity 区域划分_游戏引擎_03


由于篇幅问题,只演示Label的运行时和编辑器的示例,其他都是类似的格式,就不在一一演示了。

2-3-4-2、Button按钮

按钮点击,主要交互方式。

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestOnGUI : MonoBehaviour
{
    void OnGUI()
    {
        if (GUI.Button(new Rect(20, 40, 80, 20), "点这里!"))
        {
            Debug.Log("OK");
        }
    }
}

效果图:

unity 区域划分_编辑器_04


整个带图片的按钮:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
        texture = Resources.Load<Texture2D>("1");
    }
    static Texture2D texture;
    void OnGUI()
    {
        if (GUI.Button(new Rect(20, 20, 100, 20), texture))
        {
            Debug.Log("OK");
        }
    }
}

unity 区域划分_unity_05


效果图:

unity 区域划分_unity 区域划分_06

2-3-4-3、Box矩形框

矩形框

参考代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private void OnGUI()
    {
        GUI.Box(new Rect(0, 0, 100, 100), "Box矩形框");
    }
}

效果图:

unity 区域划分_unity 区域划分_07

2-3-4-4、RepeatButton矩形框

RepeatButton按钮按住后会重复执行单击操作(只在运行时有效)。

参考代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private void OnGUI()
    {
        if (GUI.RepeatButton(new Rect(0, 0, 100, 30), "RepeatButton"))
        {
            Debug.Log("OK");
        }
    }
}

效果图:

unity 区域划分_unity_08

2-3-4-5、TextField矩形框

单行输入框。

参考代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private string textField = "";
    void OnGUI()
    {
        textField = GUI.TextField(new Rect(0, 0, 100, 30), textField);
    }
}

效果图:

unity 区域划分_c#_09

拓展:使用TextField和PasswordField、Button简简单单制作一个登陆界面:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    string useNmae;
    string passWord;
    bool isBntLogin;
    bool isSuccess;
    private void OnGUI()
    {
        useNmae = GUI.TextField(new Rect(Screen.width / 2, Screen.height / 2 - 100, 150, 30), useNmae);
        //*****密码字符的掩码字符
        passWord = GUI.PasswordField(new Rect(Screen.width / 2, Screen.height / 2 - 50, 150, 30), passWord, '*', 25);
        if (GUI.Button(new Rect(Screen.width / 2, Screen.height / 2, 150, 30), "登录"))
        {
            isBntLogin = true;
            if (useNmae.Equals("admin") && passWord.Equals("123"))
            {
                isSuccess = true;
                GUI.Label(new Rect(Screen.width / 2, Screen.height / 2+50, 150, 30), "登录成功");
            }
            else
            {
                isSuccess = false;
                GUI.Label(new Rect(Screen.width / 2, Screen.height / 2+50, 150, 30), "登录失败");
            }
        }
        if (isBntLogin)
        {
            if (isSuccess)
            {
                GUI.Label(new Rect(Screen.width / 2, Screen.height / 2 + 50, 150, 30), "登录成功");
            }
            else
            {
                GUI.Label(new Rect(Screen.width / 2, Screen.height / 2 + 50, 150, 30), "登录失败");
            }
        }
    }
}

unity 区域划分_unity_10

2-3-4-6、TextArea矩形框

多行输入框。

参考代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private string textField = "";
    void OnGUI()
    {
        textField = GUI.TextArea(new Rect(0, 0, 100, 30), textField);
    }
}

效果图:

unity 区域划分_游戏引擎_11

2-3-4-7、Toggle单选框

单选框。

参考代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private bool toggleBool;
    void OnGUI()
    {
        toggleBool = GUI.Toggle(new Rect(0, 0, 100, 30), toggleBool,"Toggle");
    }
}

效果图:

unity 区域划分_游戏引擎_12

2-3-4-8、Toolbar工具栏

工具条,工具栏组件,一般用来绘制一些功能按钮,比如:

unity 区域划分_编辑器_13

参考代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private int toolbarInt;
    private string[] toolbarStrings = { "toolbar1", "toolbar2", "toolbar3" };

    void OnGUI()
    {
        toolbarInt = GUI.Toolbar(new Rect(0, 0, 300, 30), toolbarInt, toolbarStrings);
    }
}

效果图:

unity 区域划分_游戏引擎_14

2-3-4-9、SelectionGrid网格选择形式

SelectionGrid与Toolbar类似,就是SelectionGrid有一个网格的性质,可以设置一行有多少个元素。

参考代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private int selectInt;
    private string[] selectStrings = { "grid1", "grid2", "grid3", "grid4" };

    void OnGUI()
    {
        selectInt = GUI.SelectionGrid(new Rect(0, 0, 300, 50), selectInt, selectStrings,2);
    }
}

效果图:

unity 区域划分_编辑器_15

2-3-4-10、HorizontalSlider水平滑动条

水平滑动条。

参考代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private float hSliderValue;

    void OnGUI()
    {
        //参数: 1、位置,2、值,3、最左边的值(最小值),4、最右边的值(最大值)
        hSliderValue = GUI.HorizontalSlider(new Rect(0, 0, 100, 30), hSliderValue, 0, 10);
    }
}

效果图:

unity 区域划分_unity 区域划分_16

2-3-4-11、VerticalSlider垂直滑动条

垂直滑动条。

参考代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private float vSliderValue;

    void OnGUI()
    {
        vSliderValue = GUI.VerticalSlider(new Rect(0, 0, 100, 30), vSliderValue, 0, 10);
    }
}

效果图:

unity 区域划分_游戏引擎_17

2-3-4-12、 HorizontalScrollbar水平滚动条

HorizontalScrollbar水平滚动条,跟Slider滑动条类似,但是Slider只有一个value值。

HorizontalScrollbar有size和value值与UGUI的Scrollbar组件的Value和Size类似:

unity 区域划分_编辑器_18


Size控制滑动条的大小,Value控制滑动条的值。

参考代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private float hSize;
    private float hValue;

    void OnGUI()
    {
        hValue = GUI.HorizontalScrollbar(new Rect(0, 0, 100, 30), hValue, hSize, 0, 10);
    }
}

效果图:

unity 区域划分_unity 区域划分_19

2-3-4-13、 VerticalScrollbar垂直滚动条

垂直滚动条。

参考代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private float vSize;
    private float vValue;

    void OnGUI()
    { 
        vValue = GUI.VerticalScrollbar(new Rect(0, 0, 30, 100), vValue, vSize, 0, 10);
    }
}

效果图:

unity 区域划分_unity_20

2-3-4-14、 ScrollView滚动视图

滚动视图,需要配合TextArea一起使用,用来滚动显示内容。

参考代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private Vector2 scrollViewVector = Vector2.zero;
    private string innerText = "I am inside the ScrollViewI am inside the ScrollViewI am inside the ScrollViewI am inside the ScrollViewI am inside the ScrollViewI am inside the ScrollViewI am inside the ScrollView";

    void OnGUI()
    {
        scrollViewVector=GUI.BeginScrollView(new Rect(25, 25, 100, 100), scrollViewVector, new Rect(0, 0, 400, 400));
        innerText = GUI.TextArea(new Rect(0, 0, 400, 400), innerText);
        GUI.EndScrollView();
    }
}

效果图:

unity 区域划分_c#_21

2-3-4-15、 Window窗口

可拖动窗口容器,注意,这个只在运行时生效。

对啦,再解释一下什么是运行时,什么是编辑器

运行时:就是点击Unity编辑器的运行后的状态(打包后,就是程序运行起来的状态):

unity 区域划分_unity 区域划分_22


编辑器:只在Unity编辑器中生效,是继承Unity的GUI类,用来渲染UI,像是这样:

unity 区域划分_游戏引擎_23


OK,言归正传。

参考代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestOnGUI : MonoBehaviour
{
    private Rect windowRect = new Rect(0, 0, 300, 100);
    private Rect windowRect2 = new Rect(100, 100, 300, 100);
    void OnGUI()
    {
        windowRect = GUI.Window(0, windowRect, WindowFun, "Window");
        windowRect2 = GUI.Window(1, windowRect2, WindowFun, "Window");
    }

    private void WindowFun(int id)
    {
        Debug.Log(id);
        GUI.DragWindow(new Rect(0, 0, 10000, 20));
    }
}

效果图:

unity 区域划分_c#_24

2-3-4-16、 changed判断数据变化

判断数据变化。

参考代码,不使用changed之前:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private int toolbarInt = 0;
    private string[] toolbarStrings = { "Toolbar1", "Toolbar2", "Toolbar3" };

    void OnGUI()
    {
        toolbarInt = GUI.Toolbar(new Rect(0, 0, 200, 50), toolbarInt, toolbarStrings);
        Debug.Log(toolbarInt);

        //if (GUI.changed)
        //{
        //    Debug.Log(toolbarInt);
        //}
    }
}

效果图:

unity 区域划分_编辑器_25


参考代码,使用changed:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private int toolbarInt = 0;
    private string[] toolbarStrings = { "Toolbar1", "Toolbar2", "Toolbar3" };

    void OnGUI()
    {
        toolbarInt = GUI.Toolbar(new Rect(0, 0, 200, 50), toolbarInt, toolbarStrings);

        if (GUI.changed)
        {
            Debug.Log(toolbarInt);
        }
    }
}

效果图:

unity 区域划分_unity_26


总结一下:

就是在使用GUI.changed之前,会一直渲染GUI,所以会一直打印。

但是使用GUI.changed之后,之后值改变后才会打印消息。

可以根据这个特性,制作按钮菜单,在点击按钮后才执行函数。

2-3-4-17、 BeginGroup/EndGroup分组

在一个分组内的话,组内成员的坐标会根据当前组的坐标进行偏移。

比如组的坐标是100,100,GUI.Button的坐标是0,0,那么这个GUI.Button的实际坐标是100,100。

参考代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    void OnGUI()
    {
        GUI.BeginGroup(new Rect(100, 100, 200, 200));
        GUI.Button(new Rect(0, 0, 100, 30), "我是个按钮!");
        GUI.EndGroup();
    }
}

效果图:

unity 区域划分_c#_27

2-3-4-18、Tooltip提示信息

鼠标指针悬停在具有可点击控件时的工具提示。

创建GUI控件时,将内容参数更改为接受自定义的GUIContent对象,当鼠标悬停在带有工具提示的控件上,GUI.tooltip值将会显示传入的工具提示的值。

在OnGUI代码的末尾,可以创建一个显示GUI.tooltip值的标签。

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private void OnGUI()
    {
        GUIContent gUIContent = new GUIContent("OK", "这是一个OK按钮");

        if (GUI.Button(new Rect(0, 0, 100, 30), gUIContent))
        {
            Debug.Log("OK");
        }
        GUI.Label(new Rect(0, 20, 100, 30), GUI.tooltip);
    }
}

效果图:

unity 区域划分_unity_28

2-4-5、通用参数介绍
2-4-5-1、Rect参数

设置xy以及宽高的值,有三种重载:

unity 区域划分_游戏引擎_29


unity 区域划分_游戏引擎_30

2-4-5-1、GUIContent参数

是一个综合信息参数,既可以设置文本信息又可以设置图片信息。

有6个重载:

重载

介绍

GUIContent(string text)

单独的文本

GUIContent(Texture image)

单独的图片

GUIContent(string text, Texture image)

显示文本和图片

GUIContent(string text, string tooltip)

传入文本和控件的工具提示信息

GUIContent(Texture image, string tooltip)

传入图片和控件的工具提示信息

GUIContent(string text, Texture image, string tooltip)

传入图片和图片以及控件的工具提示信息

参考代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private void OnGUI()
    {
        // 文本 + 图片
        GUIContent gUIContent = new GUIContent("OK", Resources.Load<Texture2D>("1"));
        if (GUI.Button(new Rect(0, 0, 100, 30), gUIContent))
        {
            Debug.Log("OK");
        }
    }
}

效果图:

unity 区域划分_c#_31

2-4-5-1、GUIStyle参数

自定义样式,该参数可以让我们自定义组件的样式。

比如可以设置文字的大小、居中、图片位置、字体样式、固定宽度等。

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("TestGUI/OnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private void OnGUI()
    {
        GUIStyle gUIStyle = new GUIStyle("Command")
        {
            fontSize = 12,//设置字体大小
            alignment = TextAnchor.MiddleCenter,//设置居中方式
            imagePosition = ImagePosition.ImageAbove,//设置图片位置,图片在文字上方。
            fontStyle = FontStyle.Normal,//设置字体样式
            fixedWidth = 300//设置固定宽度
        };

        GUI.Label(new Rect(0, 0, 300, 30), "这是一个示例Label", gUIStyle);
    }
}

效果图:

unity 区域划分_unity_32

2-4-5-1、GUIskin参数

GUIskin就是内置的所有GUIStyle。

可以自己写一个脚本去查看内置的GUIStyle。

参考代码:

using UnityEngine;
using UnityEditor;

public class GUIStyleViewer : EditorWindow
{

    Vector2 scrollPosition = new Vector2(0, 0);
    string search = "";
    GUIStyle textStyle;

    private static GUIStyleViewer window;
    [MenuItem("Tool/GUIStyleViewer", false, 10)]
    private static void OpenStyleViewer()
    {
        window = GetWindow<GUIStyleViewer>(false, "内置GUIStyle");
    }

    void OnGUI()
    {
        if (textStyle == null)
        {
            textStyle = new GUIStyle("HeaderLabel");
            textStyle.fontSize = 25;
        }

        GUILayout.BeginHorizontal("HelpBox");
        GUILayout.Label("结果如下:", textStyle);
        GUILayout.FlexibleSpace();
        GUILayout.Label("Search:");
        search = EditorGUILayout.TextField(search);
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal("PopupCurveSwatchBackground");
        GUILayout.Label("样式展示", textStyle, GUILayout.Width(300));
        GUILayout.Label("名字", textStyle, GUILayout.Width(300));
        GUILayout.EndHorizontal();


        scrollPosition = GUILayout.BeginScrollView(scrollPosition);

        foreach (var style in GUI.skin.customStyles)
        {
            if (style.name.ToLower().Contains(search.ToLower()))
            {
                GUILayout.Space(15);
                GUILayout.BeginHorizontal("PopupCurveSwatchBackground");
                if (GUILayout.Button(style.name, style, GUILayout.Width(300)))
                {
                    EditorGUIUtility.systemCopyBuffer = style.name;
                    Debug.LogError(style.name);
                }
                EditorGUILayout.SelectableLabel(style.name, GUILayout.Width(300));
                GUILayout.EndHorizontal();
            }
        }

        GUILayout.EndScrollView();
    }
}

效果图:

unity 区域划分_游戏引擎_33


unity 区域划分_编辑器_34

2-4、GUILayout类

2-4-1、简介

自动布局的GUI类,提供了GUI类相同类型的控件函数,但不需要指定控件的位置和宽高,而是根据一些参数(宽度、高度、最大值、最小值、固定宽度、左右对齐)来自动计算和调整空间的布局。

支持运行时和编辑器

2-4-2、静态函数

函数名

介绍

BeginArea

在一个固定的屏幕区域中开始 GUI 控件的 GUILayout 块。

BeginHorizontal

开始一个水平控件组。

BeginScrollView

开始一个自动布局的滚动视图。

BeginVertical

开始一个垂直控件组。

Box

创建一个自动布局框。

Button

创建一个单击按钮。

EndArea

闭合以 BeginArea 开始的 GUILayout 块。

EndHorizontal

闭合以 BeginHorizontal 开始的组。

EndScrollView

结束通过 BeginScrollView 调用开始的滚动视图。

EndVertical

闭合以 BeginVertical 开始的组。

ExpandHeight

传递给控件以允许或禁止垂直扩展的选项。

ExpandWidth

传递给控件以允许或禁止水平扩展的选项。

FlexibleSpace

插入灵活的空白元素。

Height

传递给控件以使其具有绝对高度的选项。

HorizontalScrollbar

创建一个水平滚动条。

HorizontalSlider

用户可以拖动的水平滑动条,用于在最小值和最大值之间更改某值。

Label

创建一个自动布局标签。

MaxHeight

传递给控件以指定最大高度的选项。

MaxWidth

传递给控件以指定最大宽度的选项。

MinHeight

传递给控件以指定最小高度的选项。

MinWidth

传递给控件以指定最小宽度的选项。

PasswordField

创建一个可让用户输入密码的文本字段。

RepeatButton

创建一个重复按钮。只要用户按住鼠标,该按钮就返回 true。

SelectionGrid

创建一个选择网格。

Space

在当前布局组中插入空白元素。

TextArea

创建一个可供用户编辑字符串的多行文本字段。

TextField

创建一个可供用户编辑字符串的单行文本字段。

Toggle

创建一个打开/关闭的开关按钮。

Toolbar

创建一个工具栏。

VerticalScrollbar

创建一个垂直滚动条。

VerticalSlider

用户可以拖动的垂直滑动条,用于在最小值和最大值之间更改某值。

Width

传递给控件以使其具有绝对宽度的选项。

Window

创建一个对自身内容进行自动布局的弹出窗口。

2-4-3、示例代码和演示

因为GUILayout类和GUI类的大部门控件的使用方法一致,原来是GUI.Label改成GUILayout.Label即可。

这里就不再重复演示了,只用一个示例代码来演示一下自动布局的使用。

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private string textFiled;
    private string textArea;
    private string textPassword = string.Empty;
    private float sliderValue;
    private Vector2 scollView;
    private bool toggle = true;
    private bool oldtoggle;
    private int toggleIndex;
    private int selectGrid;
    private void OnGUI()
    {
        GUILayout.Label("Hello IMGUI");
        scollView = GUILayout.BeginScrollView(scollView);
        {
            GUILayout.BeginVertical("box");
            {
                GUILayout.BeginHorizontal();
                {
                    GUILayout.Label("TextField:");
                    textFiled = GUILayout.TextField(textFiled);
                }
                GUILayout.EndHorizontal();

                GUILayout.BeginHorizontal();
                {
                    GUILayout.Label("TextArea:");
                    textArea = GUILayout.TextArea(textArea);
                }
                GUILayout.EndHorizontal();

                GUILayout.BeginHorizontal();
                {
                    GUILayout.Label("PasswordField:");
                    textPassword = GUILayout.PasswordField(textPassword, '*');
                }
                GUILayout.EndHorizontal();

                GUILayout.BeginHorizontal();
                {
                    GUILayout.Label("Button");
                    GUILayout.FlexibleSpace();
                    if (GUILayout.Button("Button", GUILayout.Width(150), GUILayout.Height(150)))
                    {
                        Debug.Log("Button is Clicked!");
                    }
                }
                GUILayout.EndHorizontal();

                GUILayout.Space(20);

                GUILayout.BeginHorizontal();
                {
                    GUILayout.Label("RepeatButton");
                    if (GUILayout.RepeatButton("RepeatButton"))
                    {
                        Debug.Log("RepeatButton is Clicked!");
                    }
                }
                GUILayout.EndHorizontal();

                GUILayout.BeginHorizontal();
                {
                    GUILayout.Label("Box");
                    GUILayout.Box("AutoLayoutBox");
                }
                GUILayout.EndHorizontal();

                GUILayout.BeginHorizontal();
                {
                    GUILayout.Label("HorizontalSlider");
                    sliderValue = GUILayout.HorizontalSlider(sliderValue, 0, 1);
                }
                GUILayout.EndHorizontal();
                GUILayout.Space(10);
                GUILayout.BeginHorizontal();
                {
                    toggle = GUILayout.Toggle(toggle, "Toggle");
                    if (!oldtoggle.Equals(toggle))
                    {
                        oldtoggle = toggle;
                    }
                }
                GUILayout.EndHorizontal();
                GUILayout.Space(10);
                GUILayout.BeginHorizontal();
                {
                    toggleIndex = GUILayout.Toolbar(toggleIndex, new[] { "1", "2", "3", "4" });
                }
                GUILayout.EndHorizontal();

                GUILayout.BeginHorizontal();
                {
                    selectGrid = GUILayout.SelectionGrid(selectGrid, new[] { "1", "2", "3", "4", "5" }, 3);
                }
                GUILayout.EndHorizontal();
            }
            GUILayout.EndVertical();
        }
        GUILayout.EndScrollView();  
    }
}

效果图:

unity 区域划分_unity 区域划分_35

2-4-4、常用函数介绍
2-4-4-1、BeginHorizontal / EndHorizontal

开启/关闭一个水平控件组。

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }


    private void OnGUI()
    {
        GUILayout.BeginHorizontal();
        GUILayout.Button("1");
        GUILayout.Button("2");
        GUILayout.Button("3");
        GUILayout.EndHorizontal();
    }
}

效果图:

unity 区域划分_编辑器_36

2-4-4-2、BeginVertical / EndVertical

开启/关闭一个水平控件组。

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }


    private void OnGUI()
    {
        GUILayout.BeginVertical();
        GUILayout.Button("1");
        GUILayout.Button("2");
        GUILayout.Button("3");
        GUILayout.EndVertical();
    }
}

效果图:

unity 区域划分_c#_37

2-4-4-3、BeginArea / EndArea

在一个固定的屏幕区域中开始/结束GUI控件的GUILayout块。

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }


    private void OnGUI()
    {
        GUILayout.BeginArea(new Rect(100, 100, 100, 60));
        GUILayout.Button("1");
        GUILayout.Button("2");
        GUILayout.Button("3");
        GUILayout.EndArea();
    }
}

效果图:

unity 区域划分_游戏引擎_38

2-4-4-4、BeginScrollView / EndScrollView

开始/结束一个自动布局的滚动视图。

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private Vector2 scollView;
    private void OnGUI()
    {
        scollView = GUILayout.BeginScrollView(scollView);
        {
            GUILayout.Button("1");
            GUILayout.Button("2");
            GUILayout.Button("3");
            GUILayout.Button("1");
            GUILayout.Button("2");
            GUILayout.Button("3");
            GUILayout.Button("1");
            GUILayout.Button("2");
            GUILayout.Button("3");
            GUILayout.Button("1");
            GUILayout.Button("2");
            GUILayout.Button("3");
            GUILayout.Button("1");
            GUILayout.Button("2");
            GUILayout.Button("3");
        }
        GUILayout.EndScrollView();
    }
}

效果图:

unity 区域划分_游戏引擎_39

2-4-4-5、GUILayout.Space(x) / GUILayout.FlexibleSpace()

插入固定空白元素 / 插入灵活的空白元素。

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private Vector2 scollView;
    private void OnGUI()
    {
        GUILayout.BeginHorizontal();
        GUILayout.Button("1");
        GUILayout.Space(20);
        GUILayout.Button("2");
        GUILayout.FlexibleSpace();
        GUILayout.Button("3");
        GUILayout.EndHorizontal();
    }
}

效果图:

unity 区域划分_unity 区域划分_40

2-4-4-6、GUILayout.Width(x) / GUILayout.Height(x)

设置控件的绝对宽度 / 绝对高度的选项。

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private Vector2 scollView;
    private void OnGUI()
    {
        GUILayout.BeginHorizontal();
        GUILayout.Button("1");
        GUILayout.Button("2",GUILayout.Width(20),GUILayout.Height(20));
        GUILayout.Button("3");
        GUILayout.EndHorizontal();
    }
}

效果图:

unity 区域划分_c#_41

2-5、EditorGUI类

2-5-1、简介

专门用于编辑器界面的GUI类,提供了Unity内置类或结构体的控件函数,比如Color类、Vector3类等定义的控件。

为编辑器在Inspector和EditorWindow中扩展提供了很大的方便。

2-5-2、静态函数

函数

说明

BeginChangeCheck

启动一个新代码块来检查 GUI 更改。

BeginDisabledGroup

创建一组可禁用的控件。

BeginFoldoutHeaderGroup

创建一个左侧带有折叠箭头的标签。

BeginProperty

创建一个属性封装器,可用于使常规 GUI 控件与 SerializedProperty 配合使用。

BoundsField

创建用于输入 Bounds 的 Center 和 Extents 字段。

BoundsIntField

创建用于输入 BoundsInt 的 Position 和 Size 字段。

CanCacheInspectorGUI

确定能否缓存 SerializedProperty 的检视面板 GUI。

ColorField

创建一个用于选择 Color 的字段。

CurveField

生成一个用于编辑 AnimationCurve 的字段。

DelayedDoubleField

创建一个用于输入双精度浮点数的延迟文本字段。

DelayedFloatField

创建一个用于输入浮点数的延迟文本字段。

DelayedIntField

创建一个用于输入整数的延迟文本字段。

DelayedTextField

创建一个延迟文本字段。

DoubleField

生成一个用于输入双精度浮点数的文本字段。

DrawPreviewTexture

在矩形内绘制纹理。

DrawRect

在当前编辑器窗口中的指定位置以指定大小绘制一个着色的矩形。

DrawTextureAlpha

在矩形内绘制纹理的 Alpha 通道。

DropdownButton

创建一个能够对鼠标按下做出反应的按钮,用于显示您自己的下拉菜单内容。

DropShadowLabel

绘制带有投影的标签。

EndChangeCheck

结束代码块并检查是否有任何 GUI 更改。

EndDisabledGroup

结束由 BeginDisabledGroup 开始的禁用组。

EndFoldoutHeaderGroup

关闭以 BeginFoldoutHeaderGroup 开头的组。 另请参阅:EditorGUILayout.BeginFoldoutHeaderGroup。

EndProperty

结束由 BeginProperty 开始的属性封装器。

EnumFlagsField

在单击枚举类型的每个值时显示带有选项的菜单。一个名称为“Nothing”的值0选项和一个名称为“Everything”的值0(即所有位设置)选项总是显示在菜单的顶部。值0和0的名称可以通过在enum类型中定义这些值来重写。

EnumPopup

创建一个枚举弹出选择字段。

FloatField

创建一个用于输入浮点数的文本字段。

FocusTextInControl

将键盘焦点移动到指定的文本字段,并开始编辑内容。

Foldout

创建一个左侧带有折叠箭头的标签。

GetPropertyHeight

获取 PropertyField 控件所需的高度。

GradientField

创建一个用于编辑 Gradient 的字段。

HandlePrefixLabel

为一些控件创建一个标签。

HelpBox

创建一个带有发送给用户的消息的帮助框。

InspectorTitlebar

创建一个类似于 Inspector 窗口的标题栏。

IntField

创建一个用于输入整数的文本字段。

IntPopup

创建一个整数弹出选择字段。

IntSlider

创建一个滑动条,用户可以进行拖动以在最小值和最大值之间更改整数值。

LabelField

创建一个标签字段。(用于显示只读信息。)

LayerField

创建一个层选择字段。

LinkButton

Make a clickable link label.

LongField

创建一个用于输入长整数的文本字段。

MaskField

创建一个适用于掩码的字段。

MinMaxSlider

创建一个特殊滑动条,用户可利用该滑动条指定最小值和最大值之间的一个范围。

MultiFloatField

创建一个带有文本字段的多控件,用于在同一行中输入多个浮点值。

MultiIntField

创建一个带有文本字段的多控件,用于在同一行中输入多个整数。

MultiPropertyField

创建一个在同一行中包含多个属性字段的多控件。

ObjectField

创建一个对象字段。您可以通过拖放对象或使用对象选择器选择对象来分配对象。

PasswordField

创建一个可让用户输入密码的文本字段。

Popup

创建一个通用弹出选择字段。

PrefixLabel

创建一个显示在特定控件前的标签。

ProgressBar

创建一个进度条。

PropertyField

使用此方法在编辑器中针对 SerializedProperty 创建一个字段。

RectField

创建用于输入 Rect 的 X、Y、W 和 H 字段。

RectIntField

创建用于输入 RectInt 的 X、Y、W 和 H 字段。

SelectableLabel

创建一个可选择标签字段。(用于显示可复制粘贴的只读信息。)

Slider

创建一个滑动条,用户可以进行拖动以在最小值和最大值之间更改值。

TagField

创建一个标签选择字段。

TextArea

创建一个文本区域。

TextField

创建一个文本字段。

Toggle

创建一个开关。

ToggleLeft

创建一个开关字段,其中开关位于左侧,标签紧随其右。

Vector2Field

创建用于输入 Vector2 的 X 和 Y 字段。

Vector2IntField

创建用于输入 Vector2Int 的 X 和 Y 整数字段。

Vector3Field

创建用于输入 Vector3 的 X、Y 和 Z 字段。

Vector3IntField

创建用于输入 Vector3Int 的 X、Y 和 Z 整数字段。

Vector4Field

创建用于输入 Vector4 的 X、Y、Z 和 W 字段。

2-5-3、常用函数介绍

这些函数的运行方式与常规的GUI函数十分相似。
比如:

  • GUI: GUI.TextField(Rect,String);
  • GUILayout: GUILayout.TextField(String);
  • EditorGUI: EditorGUI.TextField(Rect,String);
  • EditorGUILayout: EditorGUILayout.TextField(String);

并且在EditorGUILayout也有匹配实现。但是EditorGUI和EditorGUILayout都是只支持编辑器。

2-5-3-1、Foldout折叠菜单

折叠菜单。

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }


    private bool _foldoutValue = true;

    public void OnGUI()
    {
        _foldoutValue = EditorGUI.Foldout(new Rect(0, 0, 20, 20), _foldoutValue, "折叠");
        if (_foldoutValue)
        {
            if(EditorGUI.LinkButton(new Rect(20, 20, 100, 30), "超链接"))
            {
                Application.OpenURL("www.baidu.com");
            }
        }
    }  
}

效果图:

unity 区域划分_c#_42

unity 区域划分_游戏引擎_43

2-5-3-2、BeginChangeCheck / EndChangeCheck 监听值改变

监听值改变,可以监听控件的值改变,跟GUI的changed参数比较类似。

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }


    private bool _foldoutValue;
    private bool _isChange;

    public void OnGUI()
    {
        _foldoutValue = EditorGUI.Foldout(new Rect(0, 0, 20, 20), _foldoutValue, "折叠");
        if (_foldoutValue)
        {
            EditorGUI.BeginChangeCheck();
            _isChange = EditorGUI.Toggle(new Rect(0, 20, 20, 20), "Change", _isChange);
            if (EditorGUI.EndChangeCheck())
            {
                Debug.Log("Toggle is change !");
            }
        }
    }  
}

效果图:

unity 区域划分_unity 区域划分_44

2-5-3-3、BeginDisabledGroup / EndDisabledGroup 是否禁用组中的控件

禁用组中的控件。

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }


    bool _foldoutValue;
    bool _isDisable;
    string _textField;
    string _passwordFile;

    public void OnGUI()
    {
        _foldoutValue = EditorGUI.Foldout(new Rect(0, 0, 20, 20), _foldoutValue, "折叠");
        if (_foldoutValue)
        {
            _isDisable = EditorGUI.Toggle(new Rect(0, 20, 20, 20), "Disable", _isDisable);
            EditorGUI.BeginDisabledGroup(_isDisable);
            _textField = EditorGUI.TextField(new Rect(0, 40, 200, 20), "账号:", _textField);
            _passwordFile = EditorGUI.PasswordField(new Rect(0, 60, 200, 20), "密码:", _passwordFile);
            EditorGUI.EndDisabledGroup();  
        }
    }  
}

效果图:

unity 区域划分_c#_45


unity 区域划分_c#_46

2-5-3-4、DropdownButton 下拉菜单

下拉菜单。

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }


    bool _foldoutValue;
    bool _isDisable;
    string _textField;
    string _passwordFile;

    public void OnGUI()
    {
        _foldoutValue = EditorGUI.Foldout(new Rect(0, 0, 20, 20), _foldoutValue, "折叠");
        if (_foldoutValue)
        {
            if (EditorGUI.DropdownButton(new Rect(0, 20, 200, 40), new GUIContent("下拉菜单"), FocusType.Keyboard))
            {
                GenericMenu genericMenu = new GenericMenu();
                genericMenu.AddItem(new GUIContent("Setting"), false, () => { Debug.Log("回调函数"); });
                genericMenu.AddSeparator(string.Empty);//分割线
                genericMenu.AddItem(new GUIContent("Export"), false, () => { });
                genericMenu.AddItem(new GUIContent("Import"), false, () => { });
                genericMenu.DropDown(new Rect(0, 20, 20, 20));
            }  
        }
    }  
}

效果图:

unity 区域划分_unity 区域划分_47

2-5-3-5、LinkButton 超链接

超链接按钮。

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }


    public void OnGUI()
    {
        if (EditorGUI.LinkButton(new Rect(0, 0, 100, 30), "超链接"))
        {
            Application.OpenURL("www.baidu.com");
        }
    }  
}

效果图:

unity 区域划分_游戏引擎_48

2-5-3-6、ColorField 颜色字段

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    Color _colorFiled;
    public void OnGUI()
    {
        _colorFiled = EditorGUI.ColorField(new Rect(0,0,200,20), _colorFiled);
    }  
}

效果图:

unity 区域划分_unity_49

2-5-3-7、BoundsField 边界盒字段

返回Bounds,由用户收入值,制作Center和Extents字段,用于输入一个Bounds。

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    Bounds _boundsFiledValue;
    public void OnGUI()
    {
        _boundsFiledValue = EditorGUI.BoundsField(new Rect(0, 0, 200, 20), _boundsFiledValue);
    }  
}

效果图:

unity 区域划分_编辑器_50

2-5-3-7、CurveField 动画曲线面板

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private AnimationCurve _animationCurveValue = new AnimationCurve();
    public void OnGUI()
    {
        _animationCurveValue = EditorGUI.CurveField(new Rect(0, 0, 200, 20), _animationCurveValue);
    }
}

效果图:

unity 区域划分_unity 区域划分_51

2-5-3-7、GradientField GradientField字段

创建一个用于编辑 Gradient 的字段。

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    Gradient gradient = new Gradient();
    public void OnGUI()
    {
        gradient = EditorGUILayout.GradientField(gradient);
    }
}

效果图:

unity 区域划分_c#_52

2-5-3-7、ObjectField 对象选择器

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private Sprite _objectFieldValue;
    public void OnGUI()
    {
        _objectFieldValue = (Sprite)EditorGUI.ObjectField(new Rect(0, 0, 50, 50), _objectFieldValue, typeof(Sprite), true);
    }
}

效果图:

2-5-4、示例代码和演示

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private Rect _labelRect = new Rect(20, 100, 300, 20);
    private Rect _changeToggleRect = new Rect(20, 130, 300, 20);
    private Rect _toggleRect = new Rect(20, 160, 100, 20);
    private Rect _textFiledRect = new Rect(20, 190, 300, 20);
    private Rect _textAreaRect = new Rect(20, 220, 300, 20);
    private Rect _passwordFileRect = new Rect(20, 250, 300, 20);
    private Rect _dropDownRect = new Rect(20, 280, 100, 20);
    private Rect _dropDownEndRect = new Rect(20, 300, 0, 0);
    private Rect _linkButtonRect = new Rect(20, 310, 100, 20);
    private Rect _colorFiledRect = new Rect(20, 340, 100, 20);
    private Rect _boundsFiledRect = new Rect(20, 370, 300, 20);
    private Rect _boundsIntFiledRect = new Rect(20, 420, 300, 20);
    private Rect _animationCurveRect = new Rect(20, 480, 200, 200);
    private Rect _enumPopupRect = new Rect(20, 690, 100, 20);
    private Rect _foldoutRect = new Rect(20, 80, 20, 20);
    private Rect _gradientRect = new Rect(20, 720, 100, 20);
    private Rect _objectFieldRect = new Rect(20, 750, 200, 20);
    private string _textField;
    private string _textArea = string.Empty;
    private string _passwordFile = string.Empty;
    private bool _isChange;
    private bool _isDisable;
    private Color _colorFiled = Color.black;
    private Bounds _boundsFiledValue;
    private BoundsInt _boundsIntFiledValue;
    private AnimationCurve _animationCurveValue = new AnimationCurve();
    private EnumPopup _enumPopupValue;
    private bool _foldoutValue = true;
    private Gradient _gradientValue = new Gradient();
    private Sprite _objectFieldValue;

    private enum EnumPopup
    {
        Shanghai,
        Beijing,
        Guangzhou,
        Shengzhen
    }

    public void OnGUI()
    {
        _foldoutValue = EditorGUI.Foldout(_foldoutRect, _foldoutValue, "折叠");
        if (_foldoutValue)
        {
            EditorGUI.BeginChangeCheck();
            _isChange = EditorGUI.ToggleLeft(_changeToggleRect, "Change", _isChange);
            EditorGUI.LabelField(_labelRect, "Label:", "boy is lwy");
            if (EditorGUI.EndChangeCheck())
            {
                Debug.Log("Toggle is change !");
            }

            _isDisable = EditorGUI.Toggle(_toggleRect, "Disable", _isDisable);
            EditorGUI.BeginDisabledGroup(_isDisable);
            _textField = EditorGUI.TextField(_textFiledRect, "TextField:", _textField);
            _textArea = EditorGUI.TextArea(_textAreaRect, _textArea);
            _passwordFile = EditorGUI.PasswordField(_passwordFileRect, "Password:", _passwordFile);
            EditorGUI.EndDisabledGroup();

            if (EditorGUI.DropdownButton(_dropDownRect, new GUIContent("下拉菜单"), FocusType.Keyboard))
            {
                GenericMenu genericMenu = new GenericMenu();
                genericMenu.AddItem(new GUIContent("Setting"), false, () => { });
                genericMenu.AddSeparator(string.Empty);
                genericMenu.AddItem(new GUIContent("Export"), false, () => { });
                genericMenu.AddItem(new GUIContent("Import"), false, () => { });
                genericMenu.DropDown(_dropDownEndRect);
            }
            if (EditorGUI.LinkButton(_linkButtonRect, "打开百度"))
            {
                Application.OpenURL("www.baidu.com");
            }
            _colorFiled = EditorGUI.ColorField(_colorFiledRect, _colorFiled);
            if (_colorFiled != Color.black)
            {
                GUI.color = _colorFiled;
            }
            _boundsFiledValue = EditorGUI.BoundsField(_boundsFiledRect, _boundsFiledValue);
            _boundsIntFiledValue = EditorGUI.BoundsIntField(_boundsIntFiledRect, _boundsIntFiledValue);
            _animationCurveValue = EditorGUI.CurveField(_animationCurveRect, _animationCurveValue);
            _enumPopupValue = (EnumPopup)EditorGUI.EnumPopup(_enumPopupRect, _enumPopupValue);
            _gradientValue = EditorGUI.GradientField(_gradientRect, _gradientValue);
            _objectFieldValue = (Sprite)EditorGUI.ObjectField(_objectFieldRect, _objectFieldValue, typeof(Sprite), true);
        }
    }  
}

效果图:

unity 区域划分_游戏引擎_53

2-6、EditorGUILayout类

2-6-1、简介

可以自动布局的EditorGUI类,提供了与EditorGU相同类型的控件函数,但不需要指定控件的位置和尺寸,而是根据一些可选参数来自动计算和调整控件的布局。

仅支持编辑器

2-6-2、静态函数

函数

说明

BeginBuildTargetSelectionGrouping

开始构建目标组并返回所选 BuildTargetGroup。

BeginFadeGroup

开始一个可隐藏/显示的组,并且过渡将生成动画。

BeginFoldoutHeaderGroup

创建一个左侧带有折叠箭头的标签。

BeginHorizontal

开始一个水平组并找回其矩形。

BeginScrollView

开始一个自动布局的滚动视图。

BeginToggleGroup

开始一个垂直组,带有可一次性启用或禁用所有控件的开关。

BeginVertical

开始一个垂直组并找回其矩形。

BoundsField

创建用于输入 Bounds 的 Center 和 Extents 字段。

BoundsIntField

创建用于输入 BoundsInt 的 Position 和 Size 字段。

ColorField

创建一个用于选择 Color 的字段。

CurveField

创建一个用于编辑 AnimationCurve 的字段。

DelayedDoubleField

创建一个用于输入双精度浮点数的延迟文本字段。

DelayedFloatField

创建一个用于输入浮点数的延迟文本字段。

DelayedIntField

创建一个用于输入整数的延迟文本字段。

DelayedTextField

创建一个延迟文本字段。

DoubleField

生成一个用于输入双精度值的文本字段。

DropdownButton

创建一个能够对鼠标按下做出反应的按钮,用于显示您自己的下拉菜单内容。

EditorToolbar

创建一个用指定的编辑器工具集合填充的工具栏。

EditorToolbarForTarget

创建一个工具栏,该工具栏用与目标对象的 EditorToolAttribute 匹配的编辑器工具集合来填充。

EndBuildTargetSelectionGrouping

关闭以 BeginBuildTargetSelectionGrouping 开头的组。

EndFadeGroup

关闭由 BeginFadeGroup 开始的组。

EndFoldoutHeaderGroup

关闭以 BeginFoldoutHeaderGroup 开头的组。

EndHorizontal

闭合以 BeginHorizontal 开始的组。

EndScrollView

结束使用 BeginScrollView 调用开始的滚动视图。

EndToggleGroup

关闭由 BeginToggleGroup 开始的组。

EndVertical

闭合以 BeginVertical 开始的组。

EnumFlagsField

单击后,系统会为枚举类型的每个值显示带有选项的菜单。

EnumPopup

创建一个枚举弹出选择字段。

FloatField

生成一个用于输入浮点值的文本字段。

Foldout

创建一个左侧带有折叠箭头的标签。

GetControlRect

获取编辑器控件的矩形。

GradientField

创建一个用于编辑 Gradient 的字段。

HelpBox

创建一个带有发送给用户的消息的帮助框。

InspectorTitlebar

创建一个类似于 Inspector 窗口的标题栏。

IntField

创建一个用于输入整数的文本字段。

IntPopup

创建一个整数弹出选择字段。

IntSlider

创建一个滑动条,用户可以进行拖动以在最小值和最大值之间更改整数值。

LabelField

生成一个标签字段。(用于显示只读信息。)

LayerField

创建一个层选择字段。

LinkButton

制作一个可点击的链接标签。

LongField

创建一个用于输入长整数的文本字段。

MaskField

创建一个适用于掩码的字段。

MinMaxSlider

创建一个特殊滑动条,用户可利用该滑动条指定最小值和最大值之间的一个范围。

ObjectField

生成一个可接收任何对象类型的字段。

PasswordField

创建一个可让用户输入密码的文本字段。

Popup

创建一个通用弹出选择字段。

PrefixLabel

创建一个显示在特定控件前的标签。

PropertyField

为 SerializedProperty 生成一个字段。

RectField

创建用于输入 Rect 的 X、Y、W 和 H 字段。

RectIntField

创建用于输入 RectInt 的 X、Y、W 和 H 字段。

SelectableLabel

生成一个可选择标签字段。(用于显示可复制粘贴的只读信息。)

Slider

创建一个滑动条,用户可以进行拖动以在最小值和最大值之间更改值。

Space

在上一个控件和下一个控件之间留出一个小空间。

TagField

创建一个标签选择字段。

TextArea

创建一个文本区域。

TextField

创建一个文本字段。

Toggle

创建一个开关。

ToggleLeft

创建一个开关字段,其中开关位于左侧,标签紧随其右。

ToolContextToolbar

使用指定的编辑器工具上下文集合填充工具栏。

ToolContextToolbarForTarget

用EditorToolContext匹配EditorToolContextAttribute的集合填充工具栏。target目标对象类型。

Vector2Field

创建用于输入 Vector2 的 X 和 Y 字段。

Vector2IntField

创建用于输入 Vector2Int 的 X 和 Y 整数字段。

Vector3Field

创建用于输入 Vector3 的 X、Y 和 Z 字段。

Vector3IntField

创建用于输入 Vector3Int 的 X、Y 和 Z 整数字段。

Vector4Field

创建用于输入 Vector4 的 X、Y、Z 和 W 字段。

2-6-3、常用函数介绍
2-6-3-1、BeginToggleGroup / EndToggleGroup

开始 / 关闭一个垂直组,带有可一次性启用或禁用所有控件的开关。

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.AnimatedValues;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private AnimBool _fadeGroup = new AnimBool(true);
    private bool _toggleEnable = true;
    public void OnGUI()
    {
        _toggleEnable = EditorGUILayout.BeginToggleGroup("Enable", _toggleEnable);
        {
            _fadeGroup.target = EditorGUILayout.ToggleLeft("Open Fade Group", _fadeGroup.target);
        }
        EditorGUILayout.EndToggleGroup();
    }  
}

效果图:

unity 区域划分_unity_54


unity 区域划分_c#_55


有点那个味了啊:

unity 区域划分_游戏引擎_56

2-6-3-2、BeginFadeGroup / EndFadeGroup

开始 / 关闭 一个可 隐藏 / 显示 的组,并且过渡将生成动画。

需要配合BeginFoldoutHeaderGroup/EndFoldoutHeaderGroup分组使用。

示意代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.AnimatedValues;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private bool _foldoutGroup = true;
    private AnimBool _fadeGroup = new AnimBool(true);
    public void OnGUI()
    {
        if (EditorGUILayout.BeginFadeGroup(_fadeGroup.faded))
        {
            _foldoutGroup = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutGroup, "FoldoutGroup");
            if (_foldoutGroup)
            {
                EditorGUILayout.LabelField("Hello EditorGUILayout!");
            }
            EditorGUILayout.EndFoldoutHeaderGroup();
        }
        EditorGUILayout.EndFadeGroup();  
    }  
}

效果图:

unity 区域划分_unity_57

2-6-3-3、BeginFoldoutHeaderGroup / EndFoldoutHeaderGroup

创建一个左侧带有折叠箭头的标签。

参考代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.AnimatedValues;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private bool _foldoutGroup = true;
    private AnimBool _fadeGroup = new AnimBool(true);
    public void OnGUI()
    {
        if (EditorGUILayout.BeginFadeGroup(_fadeGroup.faded))
        {
            _foldoutGroup = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutGroup, "FoldoutGroup");
            if (_foldoutGroup)
            {
                EditorGUILayout.LabelField("Hello EditorGUILayout!");
            }
            EditorGUILayout.EndFoldoutHeaderGroup();
        }
        EditorGUILayout.EndFadeGroup();  
    }  
}

效果图:

unity 区域划分_unity_57

2-6-3-4、BeginBuildTargetSelectionGrouping / EndBuildTargetSelectionGrouping

开始 / 结束构建目标组并返回所选 BuildTargetGroup。

参考代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.AnimatedValues;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private bool _foldoutGroup = true;
    private AnimBool _fadeGroup = new AnimBool(true);
    private BuildTargetGroup _buildTargetGroup;
    public void OnGUI()
    {
        if (EditorGUILayout.BeginFadeGroup(_fadeGroup.faded))
        {
            _foldoutGroup = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutGroup, "FoldoutGroup");
            if (_foldoutGroup)
            {
                _buildTargetGroup = EditorGUILayout.BeginBuildTargetSelectionGrouping();
                EditorGUILayout.EndBuildTargetSelectionGrouping();
                EditorGUILayout.HelpBox("Info", MessageType.Info);
                EditorGUILayout.HelpBox("Warning", MessageType.Warning);
                EditorGUILayout.HelpBox("Error", MessageType.Error);
            }
            EditorGUILayout.EndFoldoutHeaderGroup();
        }
        EditorGUILayout.EndFadeGroup();  
    }  
}

效果图:

unity 区域划分_c#_59

2-6-3-5、HelpBox

创建一个带有发送给用户的消息的帮助框。

参考代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.AnimatedValues;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    public void OnGUI()
    {
        EditorGUILayout.HelpBox("Info", MessageType.Info);
    }  
}

示意图:

unity 区域划分_unity_60

2-6-3-6、Separator

分隔符。

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.AnimatedValues;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    public void OnGUI()
    {
        EditorGUILayout.HelpBox("Info", MessageType.Info);
        EditorGUILayout.Separator();
        EditorGUILayout.HelpBox("Info", MessageType.Info);
    }  
}

效果图:

unity 区域划分_游戏引擎_61

2-6-3-7、TagField

创建一个标签选择字段。

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.AnimatedValues;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    string _tagFiled;
    public void OnGUI()
    {
        _tagFiled = EditorGUILayout.TagField("TagField:", _tagFiled);
    }  
}

效果图:

unity 区域划分_unity 区域划分_62

2-6-4、示例代码和演示

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.AnimatedValues;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorGUI : EditorWindow
{
    [MenuItem("Tool/TestOnGUI")]
    private static void OpenGUIExample()
    {
        GetWindow<TestEditorGUI>().Show();
    }

    private BuildTargetGroup _buildTargetGroup;
    private AnimBool _fadeGroup = new AnimBool(true);
    private bool _foldoutGroup = true;
    private bool _toggleEnable = true;
    private string _tagFiled;
    private GameObject _objectField;
    public void OnGUI()
    {
        _toggleEnable = EditorGUILayout.BeginToggleGroup("Enable", _toggleEnable);
        {
            _fadeGroup.target = EditorGUILayout.ToggleLeft("Open Fade Group", _fadeGroup.target);
            if (EditorGUILayout.BeginFadeGroup(_fadeGroup.faded))
            {
                _foldoutGroup = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutGroup, "FoldoutGroup");
                if (_foldoutGroup)
                {
                    EditorGUILayout.LabelField("Hello EditorGUILayout!");
                    _buildTargetGroup = EditorGUILayout.BeginBuildTargetSelectionGrouping();
                    EditorGUILayout.EndBuildTargetSelectionGrouping();
                    EditorGUILayout.HelpBox("Info", MessageType.Info);
                    EditorGUILayout.HelpBox("Warning", MessageType.Warning);
                    EditorGUILayout.HelpBox("Error", MessageType.Error);
                    EditorGUILayout.Separator();
                    _tagFiled = EditorGUILayout.TagField("TagField:", _tagFiled);
                    _objectField = (GameObject)EditorGUILayout.ObjectField(_objectField, typeof(GameObject), true);

                }
                EditorGUILayout.EndFoldoutHeaderGroup();
            }
            EditorGUILayout.EndFadeGroup();
        }
        EditorGUILayout.EndToggleGroup();
    }  
}

效果图:

unity 区域划分_游戏引擎_63

三、后记

IMGUI主要的四个API就是GUI、GUILayout、EditorGUI、EditorGUILayout了,这是最基本的知识点,其实平常可以使用Unity编辑器时想着自己去扩展应该如何操作,Unity内部的组件基本上都可以自己自定义的拓展。