Unity中UI系统——IMGUI(GUI)

本文详细介绍了Unity中的GUI系统,包括工作原理、主要作用以及各种控件的使用,如文本、按钮、多选框、单选框、输入框、拖动条、图片绘制、框绘制、工具栏、选择网格、滚动列表、分组、窗口和自定义皮肤。还探讨了GUILayout的自动布局功能和布局选项。这些内容对于Unity开发者理解和创建游戏内调试工具、自定义编辑器界面和内部游戏工具非常有帮助。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.工作原理和主要作用

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

public class lesson1 : MonoBehaviour
{
    #region GUI是什么
    //全称 即时模式游戏用户交互界面(IMGUI)
    //在Unity中一般简称为GUI
    //它是一个代码驱动的UI系统
    #endregion

    #region GUI的主要作用
    //1.作为程序员的调试工具 创建游戏内调试工具
    //2.为脚本组件创建自定义检视面板
    //3.创建新的编辑器窗口和工具以拓展Unity本身(一般用作内置游戏工具)

    //注意:不要用它为玩家制作UI功能
    #endregion

    #region GUI的工作原理
    //在继承MonoBehaviour的脚本中的特殊函数里
    //调用GUI提供的方法
    //类似生命周期函数
    private void OnGUI()
    {
        //在其中书写 GUI相关代码 即可显示GUI内容
    }
    //注意:
    //1.它每帧执行 相当于是用于专门绘制GUI界面的函数
    //2.一般只在其中执行GUI相关界面绘制和操作逻辑
    //3.该函数 在 OnDisable之前 LateUpdate之后执行
    //4.只要是继承Mono的脚本 都可以在OnGUI中绘制GUI
    #endregion
}

2.文本和按钮控件

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

public class lesson2 : MonoBehaviour
{
    public Texture tex;
    public Rect rect;
    
    public Rect rect1;

    public GUIContent content;

    public GUIStyle style;

    public Rect btnRect;
    public GUIContent btnContent;
    public GUIStyle btnStyle;
    private void OnGUI()
    {
        #region GUI控件绘制的共同点
        //1.他们都是GUI公共类中提供的静态函数 直接调用即可
        //2.他们的参数都大同小异
        //  位置参数:Rect参数 x y位置 w h尺寸
        //  显示文本:string参数
        //  图片信息:Texture参数
        //  综合信息:GUIContent参数
        //  自定义样式:GUIStyle参数
        //3.每一种控件都有多种重载,都是各个参数的排列组合  
        //  必备的参数内容 是 位置信息和显示信息
        #endregion

        #region 文本控件
        //基本使用
        GUI.Label(new Rect(0,0,100,20),"欢迎你!!!");//显示文本
        GUI.Label(rect, tex);//显示图片
        
        //综合使用
        GUI.Label(rect1, content);
        //可以获取当前鼠标或者键盘选中的GUI控件 对应的 tooltip信息
        Debug.Log(GUI.tooltip);

        //自定义样式
        GUI.Label(new Rect(0, 0, 100, 20), "欢迎你!!!",style);
        #endregion

        #region 按钮控件
        //基本使用
        //综合使用
        //自定义样式
        //鼠标在按钮内 按下并抬起 才会返回true
        if (GUI.Button(btnRect, btnContent, btnStyle))
        {
            //处理我们按钮点击的逻辑
            Debug.Log("按钮被点击");
        }

        //只要在长按按钮 就会一直返回true
        if (GUI.RepeatButton(btnRect, btnContent, btnStyle))
        {
            Debug.Log("长按按钮");
        }
        #endregion
    }
}

3.多选框和单选框

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

public class lesson3 : MonoBehaviour
{
    private bool isSel;
    private bool isSel2;

    private GUIStyle style;

    private int nowSelIndex = 1;

    private void OnGUI()
    {
        #region 多选框
        #region 普通样式 
        isSel = GUI.Toggle(new Rect(0, 0, 100, 30), isSel, "效果开关");
        #endregion

        #region 自定义样式 显示问题
        //修改固定宽高 fixedWidth和fixedHeight
        //修改从GUIStyle边缘到内容起始处的空间 padding

        isSel2 = GUI.Toggle(new Rect(0, 40, 100, 30), isSel2, "音效开关",style);
        #endregion
        #endregion

        #region 单选框
        //单选框是基于 多选框的实现

        if (GUI.Toggle(new Rect(0, 100, 100, 30), nowSelIndex == 1, "选项一"))
        {
            nowSelIndex = 1;
        }
        if (GUI.Toggle(new Rect(0, 140, 100, 30), nowSelIndex == 2, "选项二"))
        {
            nowSelIndex = 2;
        }
        if (GUI.Toggle(new Rect(0, 180, 100, 30), nowSelIndex == 3, "选项三"))
        {
            nowSelIndex = 3;
        }
        #endregion
    }

}

4.输入框和拖动条

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

public class lesson4 : MonoBehaviour
{
    private string inputStr="";
    private string inputPW="";

    private float nowValue = 0.5f;
    private void OnGUI()
    {
        #region 输入框
        #region 普通输入
        //输入框 重要参数 
        //参数二:内容 string
        //参数三:可输入长度
        inputStr = GUI.TextField(new Rect(0, 0, 100, 30), inputStr,5);
        #endregion

        #region 密码输入
        //参数二:密码
        //参数三:可输入长度
        inputPW = GUI.PasswordField(new Rect(0, 50, 100, 30), inputPW, '*', 5);
        #endregion
        #endregion

        #region 拖动条
        #region 水平拖动条
        //当前的值
        //参数三:最小值
        //参数四:最大值
        //可以加三个样式
        nowValue = GUI.HorizontalSlider(new Rect(0, 100, 100, 50), nowValue, 0, 1);
        Debug.Log(nowValue);
        #endregion

        #region 竖直拖动条
        nowValue = GUI.VerticalSlider(new Rect(0, 150, 50, 100), nowValue, 0, 1);
        #endregion
        #endregion
    }
}

5.图片绘制和框绘制

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

public class lesson5 : MonoBehaviour
{
    public Rect texPos;

    public Texture tex;

    public ScaleMode mode = ScaleMode.StretchToFill;
    public bool alpha = true;
    public float wh = 0;

    private void OnGUI()
    {
        #region 图片绘制
        // ScaleMode
        // ScaleAndCrop    会通过宽高比比来计算图片 但是 会进行裁剪
        // ScaleToFit      会自动根据宽高比进行计算 不会拉变形 会一直保持图片完全显示的状态
        // StretchToFiill  始终填充满你传入的 Rect范围

        // alpha 是用来 控制 图片是否开启透明通道的

        // imageAspect 自定义宽高比 如果不填 默认为0 就会使用 图片原始宽高
        //GUI.DrawTexture(texPos,tex,mode,alpha,wh);
        #endregion

        #region 框绘制
        GUI.Box(texPos, "123");
        #endregion
    }
}

6.工具栏和选择网格

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

public class lesson6 : MonoBehaviour
{
    private int toolbarIndex = 0;
    private string[] toolbarInfos = new string[] { "选项一", "选项二", "选项三" };

    private int selGridIndex = 0;
    private void OnGUI()
    {
        #region 工具栏
        toolbarIndex = GUI.Toolbar(new Rect(0, 0, 200, 30), toolbarIndex, toolbarInfos);
        //工具栏可以帮助我们根据不同的返回索引 来处理不同的逻辑
        switch (toolbarIndex)
        {
            case 0:
                break;
            case 1:
                break;
            case 2:
                break;
        }
        #endregion

        #region 选择网格
        //相对 toolbar多了一个参数 xCount 代表 水平方向最多显示的按钮数量
        //一行显示不完就会在下一行显示
        GUI.SelectionGrid(new Rect(0, 50, 200, 30), selGridIndex, toolbarInfos, 2);
        #endregion
    }
}

7.滚动列表和分组

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

public class lesson7 : MonoBehaviour
{
    public Rect groupPos;

    public Rect scPos;
    public Rect showPos;

    private Vector2 nowPos;

    private string[] strs = new string[] { "按钮1", "按钮2", "按钮3", "按钮4" };
    private void OnGUI()
    {
        #region 分组
        //用于批量控制控件位置
        //可以理解为 包裹着的控件加了一个父对象
        //可以通过控制分组来控制包裹控件的位置
        GUI.BeginGroup(groupPos);

        GUI.Button(new Rect(0, 0, 100, 50), "测试按钮");
        GUI.Label(new Rect(0, 60, 100, 20), "Lable信息");


        GUI.EndGroup();
        #endregion

        #region 滚动列表
        nowPos = GUI.BeginScrollView(scPos, nowPos, showPos);

        GUI.Toolbar(new Rect(0, 0, 300, 50), 0, strs);
        GUI.Toolbar(new Rect(0, 60, 300, 50), 0, strs);
        GUI.Toolbar(new Rect(0, 120, 300, 50), 0, strs);
        GUI.Toolbar(new Rect(0, 180, 300, 50), 0, strs);

        GUI.EndScrollView();
        #endregion
    }
}

8.窗口

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

public class lesson8 : MonoBehaviour
{
    private Rect dragWinPos = new Rect(400, 400, 200, 150);
    private void OnGUI()
    {
        #region 窗口
        //参数一:第一个参数 id 是窗口的唯一ID 不要和别的窗口重复
        //参数二:显示区域
        //参数三:委托参数 是用于 绘制窗口用的函数 传入即可
        //参数四:窗口标题

        GUI.Window(1, new Rect(100, 100, 200, 150), DrawWindow, "测试窗口");
        //id对于我们来说 有一个重要作用 除了区分不同窗口 还可以在一个函数中去处理多个窗口的逻辑
        //通过id去区分他们
        GUI.Window(2, new Rect(100, 350, 200, 150), DrawWindow, "测试窗口2");
        #endregion

        #region 模态窗口
        //模态窗口 可以让其他控件不再有用
        //你可以理解该窗口在最上层 其他按钮都点击不到了
        //只能点击该窗口上的控件

        //GUI.ModalWindow(3, new Rect(300, 100, 200, 150), DrawWindow, "模态窗口");
        #endregion

        #region 拖动窗口
        //位置赋值只是前提
        dragWinPos = GUI.Window(4, dragWinPos, DrawWindow, "拖动窗口");
        #endregion
    }
    private void DrawWindow(int id)
    {
        switch (id)
        {
            case 1:
                GUI.Button(new Rect(0, 20, 30, 20), "按钮1");
                break;
            case 2:
                GUI.Button(new Rect(0, 20, 30, 20), "按钮2");
                break;
            case 3:
                GUI.Button(new Rect(0, 20, 30, 20), "按钮3");
                break;
            case 4:
                //该API 写在窗口函数中调用 可以让窗口被拖动
                //传入Rect参数的重载 作用
                //是决定窗口中的哪一部分位置 可以被拖动
                //默认不填 就是无参重载 默认窗口的所有位置都能被拖动
                GUI.DragWindow(new Rect (0,0,1000,20));
                break;
        }
    }
}

9.自定义皮肤

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

public class lesson9 : MonoBehaviour
{
    public GUIStyle style;

    public GUISkin skin;
    private void OnGUI()
    {
        #region 全局颜色
        //全局的着色颜色 影响背景和文本颜色
        //GUI.color = Color.red;

        //文本着色颜色 会和 全局颜色相乘
        //GUI.contentColor = Color.yellow;
        //GUI.Button(new Rect(0, 0, 100, 30), "测试按钮");

        ////背景元素着色颜色 会和 全局颜色相乘
        //GUI.backgroundColor = Color.red;
        //GUI.Label(new Rect(0, 50, 100, 30), "测试按钮");
        //GUI.color = Color.white;
        //GUI.Button(new Rect(0, 100, 100, 30), "测试按钮",style);

        #endregion

        #region 整体皮肤样式
        //为空的话 会显示默认的皮肤样式
        GUI.skin = skin;
        //虽然设置了皮肤 但是绘制时 如果使用GUIStyle参数 皮肤就没有
        GUI.Button(new Rect(0, 0, 100, 30), "测试按钮");

        GUI.skin = null;
        GUI.Button(new Rect(0, 50, 100, 30), "测试按钮2");

        //它可以帮助我们整套的设置 自定义样式
        //相对单个控件设置style要方便一些
        #endregion
    }
}

10.自动布局

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

public class lesson10 : MonoBehaviour
{
    private void OnGUI()
    {
        #region GUILayout 自动布局
        //主要用于进行编辑器开发 如果用它来做游戏UI不太合适
        GUI.BeginGroup(new Rect(100, 100, 200, 300));
        GUILayout.BeginVertical();

        GUILayout.Button("123",GUILayout.Width(200));
        GUILayout.Button("1234");
        GUILayout.Button("12345",GUILayout.ExpandWidth(false));
        
        GUILayout.EndVertical();
        GUI.EndGroup();
        #endregion

        #region GUILayoutOption 布局选项
        //控件的固定宽高
        GUILayout.Width(300);
        GUILayout.Height(200);

        //运行控件的最小宽高
        GUILayout.MinWidth(50);
        GUILayout.MinHeight(50);

        //允许控件的最大宽高
        GUILayout.MaxWidth(100);
        GUILayout.MaxHeight(100);

        //允许或禁止水平拓展
        GUILayout.ExpandWidth(true);
        GUILayout.ExpandHeight(true);
        #endregion
    }
}

### 使用 ImGui 或其替代方案在 Unity 中实现自定义界面 #### 什么是 IMGUIIMGUI 是 Immediate Mode GUI 的缩写,它是一种即时模式图形用户界面的设计理念。与传统的保留模式不同,IMGUI 不会保存控件的状态,而是每次绘制时重新计算并渲染整个界面[^1]。 #### Unity 中的 IMGUI 实现 Unity 自带了一套基于 IMGUI 的 API,允许开发者通过脚本创建复杂的编辑器窗口和游戏运行时界面。以下是基本用法: ```csharp using UnityEngine; using UnityEditor; public class ExampleWindow : EditorWindow { private string inputText = "Default Text"; [MenuItem("Example/Open Window")] public static void ShowWindow() { GetWindow<ExampleWindow>("IMGUI Example"); } void OnGUI() { GUILayout.Label("Enter some text below:", EditorStyles.boldLabel); inputText = EditorGUILayout.TextField("Input Field", inputText); if (GUILayout.Button("Submit")) { Debug.Log($"You entered: {inputText}"); } } } ``` 上述代码展示了如何使用 `EditorWindow` 创建一个简单的编辑器窗口,并利用 IMGUI 提供的功能来构建交互式界面[^3]。 #### 替代方案:UI Toolkit 随着技术的发展,Unity 推出了更现代化的 UI 工具集——UI Toolkit。相比传统 IMGUIUI Toolkit 基于 C# 脚本编写,提供了更高的性能和灵活性[^2]。然而需要注意的是,在最新版本 Unity 6 中虽然推荐使用 UI Toolkit,但它并未完全覆盖 IMGUI 所有的功能特性。 如果项目需求较为复杂或者需要兼容旧版工程,则仍可以选择继续沿用经典的 IMGUI 方法;而对于新开发的应用来说,采用更加高效且易于维护的 UI Toolkit 将是一个更好的决定。 #### 总结 - 对于简单快速搭建原型以及定制化程度较高的编辑器扩展插件开发场景下可以考虑直接运用内置的IMGUI; - 如果追求跨平台一致性表现效果并且希望获得官方长期支持的话则建议转向学习掌握新的UI工具包(UI Toolkit)[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值