【Unity3D编辑器拓展】Unity3D的IMGUI、OnGUI【全面总结】

推荐阅读

大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。

一、前言

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

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

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

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

首先,放一张脉络图。
在这里插入图片描述

大图,可放大查看。

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

二、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
matrixGUI变换矩阵
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");
    }
}

效果图:
在这里插入图片描述
编辑器示例代码:

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:
在这里插入图片描述
由于篇幅问题,只演示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");
        }
    }
}

效果图:
在这里插入图片描述
整个带图片的按钮:

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");
        }
    }
}

在这里插入图片描述
效果图:
在这里插入图片描述

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矩形框");
    }
}

效果图:
在这里插入图片描述

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");
        }
    }
}

效果图:
在这里插入图片描述

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);
    }
}

效果图:
在这里插入图片描述

拓展:使用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), "登录失败");
            }
        }
    }
}

在这里插入图片描述

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);
    }
}

效果图:
在这里插入图片描述

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");
    }
}

效果图:
在这里插入图片描述

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

工具条,工具栏组件,一般用来绘制一些功能按钮,比如:
在这里插入图片描述

参考代码:

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);
    }
}

效果图:
在这里插入图片描述

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);
    }
}

效果图:
在这里插入图片描述

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);
    }
}

效果图:
在这里插入图片描述

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);
    }
}

效果图:
在这里插入图片描述

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

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

HorizontalScrollbar有size和value值与UGUI的Scrollbar组件的Value和Size类似:
在这里插入图片描述
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);
    }
}

效果图:
在这里插入图片描述

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);
    }
}

效果图:
在这里插入图片描述

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();
    }
}

效果图:
在这里插入图片描述

2-3-4-15、 Window窗口

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

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

运行时:就是点击Unity编辑器的运行后的状态(打包后,就是程序运行起来的状态):
在这里插入图片描述
编辑器:只在Unity编辑器中生效,是继承Unity的GUI类,用来渲染UI,像是这样:
在这里插入图片描述
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));
    }
}

效果图:
在这里插入图片描述

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);
        //}
    }
}

效果图:
在这里插入图片描述
参考代码,使用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);
        }
    }
}

效果图:
在这里插入图片描述
总结一下:
就是在使用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();
    }
}

效果图:
在这里插入图片描述

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);
    }
}

效果图:
在这里插入图片描述

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

设置xy以及宽高的值,有三种重载:
在这里插入图片描述
在这里插入图片描述

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");
        }
    }
}

效果图:
在这里插入图片描述

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);
    }
}

效果图:
在这里插入图片描述

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();
    }
}

效果图:
在这里插入图片描述
在这里插入图片描述

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();  
    }
}

效果图:
在这里插入图片描述

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();
    }
}

效果图:
在这里插入图片描述

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();
    }
}

效果图:
在这里插入图片描述

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();
    }
}

效果图:
在这里插入图片描述

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();
    }
}

效果图:
在这里插入图片描述

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();
    }
}

效果图:
在这里插入图片描述

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();
    }
}

效果图:
在这里插入图片描述

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创建一个层选择字段。
LinkButtonMake 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");
            }
        }
    }  
}

效果图:
在这里插入图片描述

在这里插入图片描述

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 !");
            }
        }
    }  
}

效果图:

在这里插入图片描述

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();  
        }
    }  
}

效果图:
在这里插入图片描述
在这里插入图片描述

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));
            }  
        }
    }  
}

效果图:
在这里插入图片描述

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");
        }
    }  
}

效果图:

在这里插入图片描述

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);
    }  
}

效果图:
在这里插入图片描述

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);
    }  
}

效果图:
在这里插入图片描述

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);
    }
}

效果图:
在这里插入图片描述

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);
    }
}

效果图:
在这里插入图片描述

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);
        }
    }  
}

效果图:
在这里插入图片描述

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();
    }  
}

效果图:
在这里插入图片描述
在这里插入图片描述
有点那个味了啊:
在这里插入图片描述

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();  
    }  
}

效果图:
在这里插入图片描述

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();  
    }  
}

效果图:
在这里插入图片描述

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();  
    }  
}

效果图:
在这里插入图片描述

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);
    }  
}

示意图:
在这里插入图片描述

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);
    }  
}

效果图:
在这里插入图片描述

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);
    }  
}

效果图:
在这里插入图片描述

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();
    }  
}

效果图:
在这里插入图片描述

三、后记

IMGUI主要的四个API就是GUI、GUILayout、EditorGUI、EditorGUILayout了,这是最基本的知识点,其实平常可以使用Unity编辑器时想着自己去扩展应该如何操作,Unity内部的组件基本上都可以自己自定义的拓展。
后面还会更新关于Inspector、Hierarchy、Project、Scene等窗口内容

如果觉得本篇文章有用别忘了点个关注,关注不迷路,持续分享更多Unity干货文章。


你的点赞就是对博主的支持,有问题记得留言:

博主主页有联系方式。

博主还有跟多宝藏文章等待你的发掘哦:

专栏方向简介
Unity3D开发小游戏小游戏开发教程分享一些使用Unity3D引擎开发的小游戏,分享一些制作小游戏的教程。
Unity3D从入门到进阶入门从自学Unity中获取灵感,总结从零开始学习Unity的路线,有C#和Unity的知识。
Unity3D之UGUIUGUIUnity的UI系统UGUI全解析,从UGUI的基础控件开始讲起,然后将UGUI的原理,UGUI的使用全面教学。
Unity3D之读取数据文件读取使用Unity3D读取txt文档、json文档、xml文档、csv文档、Excel文档。
Unity3D之数据集合数据集合数组集合:数组、List、字典、堆栈、链表等数据集合知识分享。
Unity3D之VR/AR(虚拟仿真)开发虚拟仿真总结博主工作常见的虚拟仿真需求进行案例讲解。
Unity3D之插件插件主要分享在Unity开发中用到的一些插件使用方法,插件介绍等
Unity3D之日常开发日常记录主要是博主日常开发中用到的,用到的方法技巧,开发思路,代码分享等
Unity3D之日常BUG日常记录记录在使用Unity3D编辑器开发项目过程中,遇到的BUG和坑,让后来人可以有些参考。
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Unity编辑器拓展(Editor Extension)可以通过自定义的脚本来扩展Unity编辑器的功能和界面,以满足特定项目的需求。通过编辑器拓展,开发者可以创建自定义的编辑器窗口、工具栏按钮、菜单项、检视面板等,来增强Unity编辑器的功能和流程。 要创建一个Unity编辑器拓展,你可以使用C#编写一个继承自Editor类的脚本。这个脚本可以通过Unity的Inspector面板来设置相关的属性和行为。以下是一个简单的示例: ```csharp using UnityEngine; using UnityEditor; public class MyEditorExtension : EditorWindow { [MenuItem("Custom Tools/My Editor Window")] public static void OpenWindow() { // 创建并打开一个自定义的编辑器窗口 MyEditorExtension window = (MyEditorExtension)EditorWindow.GetWindow(typeof(MyEditorExtension)); window.Show(); } private void OnGUI() { // 在编辑器窗口中绘制UI元素 GUILayout.Label("Hello, I am a custom editor window!"); if (GUILayout.Button("Click Me")) { Debug.Log("Button clicked!"); } } } ``` 上述代码创建了一个自定义的编辑器窗口,并在窗口中绘制了一个标签和一个按钮。通过在Unity编辑器中点击"Custom Tools"菜单下的"My Editor Window",可以打开这个自定义的编辑器窗口。 除了编辑器窗口,你还可以通过继承Editor类来创建自定义的检视面板、菜单项等。Unity官方文档中有更详细的教程和示例,可以帮助你更深入地了解和使用Unity编辑器拓展

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

恬静的小魔龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值