12.IMGUI基础知识总结

  1. 12.总结
    1. 12.1 知识点
      1. 学习的主要内容
      2. 优点
      3. 缺点
      4. 主要用处
    2. 12.2 核心要点速览
      1. IMGUI 的定位、用途与 OnGUI
      2. IMGUI 控件调用共性
      3. 文本控件(Label)
      4. 按钮控件
        1. 普通按钮(Button)
        2. 长按按钮(RepeatButton)
      5. 多选框(Toggle)
      6. 单选框(基于 Toggle 实现)
      7. 输入框
        1. 普通输入框(TextField)
        2. 密码输入框(PasswordField)
      8. 拖动条
        1. 水平拖动条(HorizontalSlider)
        2. 竖直拖动条(VerticalSlider)
      9. 图片绘制(DrawTexture)
      10. 框绘制(Box)
      11. 工具栏(Toolbar)
        1. 选择网格(SelectionGrid)
      12. 分组(BeginGroup 和 EndGroup)
      13. 滚动列表(BeginScrollView 和 EndScrollView)
      14. 窗口
        1. 普通窗口(Window)
        2. 模态窗口(ModalWindow)
        3. 拖动窗口
      15. 全局颜色和皮肤样式
        1. 全局颜色
        2. 整体皮肤样式
      16. GUILayout 自动布局
      17. GUILayoutOption 布局选项
    3. 12.3 面试题精选
      1. 基础题
        1. 1. Unity 里的 GUI 与 IMGUI 是什么关系,常见用在哪
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        2. 2. Button 和 RepeatButton 什么时候为 true
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        3. 3. 设置了 GUI.skin 为什么有的按钮还是不走皮肤
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
      2. 进阶题
        1. 1. OnGUI 的回调节奏与生命周期位置
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        2. 2. BeginScrollView 三个矩形和 scroll 向量各自干什么
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        3. 3. GUILayout 适合干什么,和 GUI.BeginGroup 怎么配合
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
      3. 深度题
        1. 1. 为什么不宜用 IMGUI 做玩家正式界面
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        2. 2. 可拖动窗口为什么要用成员 Rect 接 Window 返回值
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        3. 3. 换 GUISkin 前为什么先把三种颜色设回白色
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章

12.总结


12.1 知识点

学习的主要内容

优点

缺点

主要用处


12.2 核心要点速览

IMGUI 的定位、用途与 OnGUI

  • 名称习惯:文中把 GUI 当作 Unity 里对 IMGUI(即时模式游戏用户交互界面)的简称;控件在代码里即时声明,属于代码驱动的 UI 写法。
  • 三条主用途:运行时给程序员做调试工具与游戏内 Debug 面板;给脚本写 Inspector 自定义检视;做编辑器窗口和内置工具,扩展引擎工作流。
  • 红线:不要拿它给玩家做正式、量产的界面功能;玩家向界面通常交给 UGUI、UI Toolkit 等方案。
  • 挂载方式:在挂到对象上的 MonoBehaviour 里实现 OnGUI(),在其中调用 GUI 等 API,语义上类似生命周期里的一个绘制阶段。
要点 说明
调用节奏 按文中所述每帧进入,专门承担「这一帧 GUI 画什么、点什么」的职责。
书写边界 尽量只做 GUI 绘制与轻量交互逻辑,别把整套玩法运算堆进回调。
相对顺序 LateUpdate 之后、OnDisable 之前执行到 OnGUI
谁能写 任意继承 MonoBehaviour 的脚本都可以声明并实现 OnGUI
private void OnGUI()
{
    // 在其中书写 GUI 相关代码即可显示 GUI 内容
}

IMGUI 控件调用共性

  • 静态入口:常用控件都在 GUI 上,静态方法即调即用。
  • 坐标与尺寸:第一参数多半是 Rectxywidthheight);原点在该系列示例语境下取 Game 视图左上角,向右、向下为正。
  • 参数组合习惯:展示用 stringTexture 或包了一层的 GUIContent;要换外观再传 GUIStyle。多组重载本质是上述几类参数排列,位置和展示内容是最少要凑齐的两样。

文本控件(Label)

  • 作用:生成文本控件。

  • tooltipGUI.tooltip 为只读;本帧画完控件后,可取当前鼠标悬停或键盘焦点控件对应的 tooltip(与 GUIContent 里配的 tooltip 一起用才有内容)。

  • 重载形式

    • public static void Label(Rect position, string text);
    • public static void Label(Rect position, Texture image);
    • public static void Label(Rect position, GUIContent guiContent);
    • public static void Label(Rect position, string text, GUIStyle style);
    • public static void Label(Rect position, Texture image, GUIStyle style);
    • public static void Label(Rect position, GUIContent guiContent, GUIStyle style);
  • 使用示例

    GUI.Label(new Rect(100, 20, 100, 20), "666666欢迎你");
    GUI.Label(labelRect1, image);
    GUI.Label(labelRect2, guiContent);
    GUI.Label(new Rect(500, 200, 500, 500), "林文韬欢迎你", labelGuiStyle);
    

按钮控件

普通按钮(Button)

  • 作用:创建单击按钮,点击时执行操作,返回布尔值。

  • 点击判定:在按钮矩形内按下鼠标,并在仍算同一次点击的抬起发生在合理命中范围内,才得到一次 true;在按钮内按下却到按钮外抬起,或反过来,都不算一次有效点击。

  • 重载形式:与 Label 类似,有多种参数组合。

  • 使用示例

    if (GUI.Button(btnRect, btnGUIContent1, btnGuiStyle))
    {
        Debug.Log("按钮被点击");
    }
    

长按按钮(RepeatButton)

  • 作用:用户按住时一直处于激活状态,返回布尔值。

  • 范围:按住期间若指针移出控件矩形,离开瞬间就会变回 false,不会一直为 true

  • 使用示例

    if (GUI.RepeatButton(new Rect(300, 60, 100, 20), btnGUIContent2))
    {
        Debug.Log("长按按钮被点击");
    }
    

多选框(Toggle)

  • 作用:创建打开/关闭的开关按钮,需传入布尔值表示选中状态,返回改变后的选中状态。

  • 样式:自定义 GUIStyle 时若显示挤压、对不齐,常见是调 fixedWidthfixedHeightpadding

  • 重载形式:与 Label 类似,有多种参数组合。

  • 使用示例

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

单选框(基于 Toggle 实现)

  • 关键:通过一个 int 标识决定是否选中,改变 int 值。

  • 使用示例

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

输入框

普通输入框(TextField)

  • 作用:创建可供用户编辑字符串的单行文本字段。

  • 长度限制:传入最大长度后,超出部分无法再输入,需把返回值持续赋回字符串变量才能看到编辑结果。

  • 使用示例

    inputStr = GUI.TextField(new Rect(0, 0, 100, 30), inputStr, 5);
    

密码输入框(PasswordField)

  • 作用:创建可让用户输入密码的文本字段。

  • 使用示例

    inputPW = GUI.PasswordField(new Rect(0, 50, 100, 30), inputPW, '★');
    

拖动条

水平拖动条(HorizontalSlider)

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

  • 使用示例

    nowValue = GUI.HorizontalSlider(new Rect(0, 100, 100, 50), nowValue, 0, 1);
    

竖直拖动条(VerticalSlider)

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

  • 使用示例

    nowValue = GUI.VerticalSlider(new Rect(0, 150, 50, 100), nowValue, 0, 1);
    

图片绘制(DrawTexture)

  • 作用:在一个矩形内绘制纹理。

  • 重载形式

    • public static void DrawTexture(Rect position, Texture image);
    • public static void DrawTexture(Rect position, Texture image, ScaleMode scaleMode);
    • public static void DrawTexture(Rect position, Texture image, ScaleMode scaleMode, bool alphaBlend);
    • public static void DrawTexture(Rect position, Texture image, ScaleMode scaleMode, bool alphaBlend, float imageAspect);
  • 参数说明

    • ScaleMode:图像宽高比不适合绘制宽高比时的缩放方式,包括 ScaleAndCrop(计算后裁剪)、ScaleToFit(保持完整显示)、StretchToFill(填充满整个区域)。
    • alphaBlend:绘制图像时是否应用 Alpha 混合,控制透明通道。
    • imageAspect:源图像宽高比,为 0 时使用图像默认宽高比。
  • 使用示例

    GUI.DrawTexture(texPos, tex, mode, alpha, wh);
    

框绘制(Box)

  • 作用:在 GUI 层上创建一个框。

  • 使用示例

    GUI.Box(texPos, "123");
    

工具栏(Toolbar)

  • 作用:创建一个工具栏,需要一个 int 用于记录当前索引和一个 string 数组用于显示内容。返回新的选中索引,记得写回 int,否则选中状态不更新。

  • 示例

    int toolbarIndex = 0;
    string[] toolbarInfos = { "选项1", "选项2", "选项3" };
    
    toolbarIndex = GUI.Toolbar(new Rect(0, 0, 200, 30), toolbarIndex, toolbarInfos);
    
    switch (toolbarIndex)
    {
        case 0:
            // 逻辑处理
            break;
        case 1:
            // 逻辑处理
            break;
        case 2:
            // 逻辑处理
            break;
    }
    

选择网格(SelectionGrid)

  • 作用:创建一个按钮网格,需要一个 int 索引、string 数组内容和 xCount每行最多放几个);同样要把返回的索引赋回变量。

  • 示例

    int selGridIndex = 0;
    string[] gridInfos = { "选项1", "选项2", "选项3" };
    
    selGridIndex = GUI.SelectionGrid(new Rect(0, 50, 200, 60), selGridIndex, gridInfos, 2);
    

分组(BeginGroup 和 EndGroup)

  • 作用:批量控制控件位置,类似父对象容器。

  • 示例

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

滚动列表(BeginScrollView 和 EndScrollView)

  • 作用:创建可滚动视图。

  • 参数说明

    • position:视口在屏幕上的矩形,含滚动条占位。
    • scrollPosition:内容偏移,必须用 BeginScrollView 的返回值写回该变量,否则滚动状态留不住。
    • viewRect:逻辑内容区域大小;内容比视口高或宽才会出现滚动;动态列表常按条数乘行高改 height
  • 示例

    nowPos = GUI.BeginScrollView(scRect, nowPos, showRect);
        // 内容
    GUI.EndScrollView();
    

窗口

普通窗口(Window)

  • 作用:创建弹出窗口。

  • 参数

    • id:窗口唯一标识,多个窗口可共用一个绘制函数,在回调里用 id 分支。
    • position:位置和大小;要做拖动窗口,一般把 Rect 存成成员字段,每帧把 GUI.Window 的返回值赋回该字段。
    • function:绘制内容的回调。
  • 示例

    private void OnGUI()
    {
        GUI.Window(1, new Rect(100, 100, 200, 150), DrawWindow, "测试窗口");
        GUI.Window(2, new Rect(100, 250, 200, 150), DrawWindow, "测试窗口2");
    }
    
    private void DrawWindow(int id)
    {
        switch (id)
        {
            case 1:
                GUI.Button(new Rect(0, 30, 30, 20), "1");
                break;
            case 2:
                GUI.Button(new Rect(0, 30, 30, 20), "2");
                break;
            case 3:
                GUI.Button(new Rect(0, 30, 30, 20), "3");
                break;
        }
    }
    

模态窗口(ModalWindow)

  • 作用:显示模态窗口,其它 IMGUI 控件暂时点不到,优先处理当前弹层,适合做必须点掉的提示。

  • 示例

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

拖动窗口

  • 作用:实现窗口可拖动。

  • 配合:外层用成员 RectGUI.Window 返回值;在窗口函数里调用 GUI.DragWindow,无参则整窗可拖,传入 Rect 则只有那块区域能拖(例如标题条)。

  • 示例

    dragWinPos = GUI.Window(4, dragWinPos, DrawWindow, "拖动窗口");
    
    private void DrawWindow(int id)
    {
        switch (id)
        {
            case 4:
                GUI.DragWindow(new Rect(0, 0, 1000, 20));
                break;
        }
    }
    

全局颜色和皮肤样式

全局颜色

  • GUI.color:全局着色,相当于给后续 GUI 绘制套一层 tint。

  • GUI.contentColor:作用在文本上,与 GUI.color 相乘

  • GUI.backgroundColor:作用在背景元素上,同样与 GUI.color 相乘;三个量都动过以后,最终观感是叠乘结果,排查偏色时记得从这三处一起往回捋。

  • 示例

    GUI.color = Color.red;
    GUI.Label(new Rect(0, 50, 150, 30), "全局着色颜色标签红");
    GUI.contentColor = Color.yellow;
    GUI.Button(new Rect(0, 200, 150, 30), "文本着色颜色");
    GUI.backgroundColor = Color.green;
    GUI.Button(new Rect(0, 250, 150, 30), "背景元素着色颜色", style);
    

整体皮肤样式

  • 创建:在 Project 窗口右键创建 GUISkin 资源,拖到脚本字段再在 OnGUI 里赋给 GUI.skin

  • 使用GUI.skin = mySkin 管的是「没单独指定样式时」的默认外观;调用时若显式传了 GUIStyle,以该参数为准,当前 skin 对这类绘制不起作用

  • 换皮前:先把 GUI.colorGUI.contentColorGUI.backgroundColor 设回白色,再套皮肤,避免上一轮全局着色把新皮肤「染花」。

  • 收尾GUI.skin = null 回到内置默认皮肤。

  • 示例

    GUI.color = Color.white;
    GUI.contentColor = Color.white;
    GUI.backgroundColor = Color.white;
    GUI.skin = mySkin;
    GUI.Button(new Rect(200, 0, 100, 30), "测试按钮1");
    GUI.Button(new Rect(200, 50, 100, 30), "测试按钮2", style);
    GUI.skin = null;
    GUI.Button(new Rect(200, 100, 100, 30), "测试按钮3");
    

GUILayout 自动布局

  • 定位:API 形态与 GUI 接近,由布局系统算控件矩形;篇中写明更偏编辑器扩展,拿来堆正式游戏 UI 不合适。

  • GUI 混用:常见写法是外层 GUI.BeginGroup 定一块总区域,内层 GUILayout.BeginArea 再开自动布局区间,竖直 BeginVertical / 水平 BeginHorizontal 成对闭合,最后 EndAreaEndGroup 顺序别写反。

  • 特点:省掉大量手写 Rect 对齐,复杂排版仍要配合 GUILayoutOption

  • 示例

    GUI.BeginGroup(new Rect(100, 100, 500, 300));
        GUILayout.BeginArea(new Rect(10, 10, 400, 300));
            GUILayout.BeginVertical();
                GUILayout.Button("竖直123", GUILayout.Width(200));
                GUILayout.Button("竖直245666656565");
                GUILayout.Button("竖直235", GUILayout.ExpandWidth(false));
            GUILayout.EndVertical();
            GUILayout.BeginHorizontal();
                GUILayout.Button("水平123", GUILayout.Height(300));
                GUILayout.Button("水平245666656565");
                GUILayout.Button("水平235", GUILayout.ExpandWidth(false));
            GUILayout.EndHorizontal();
        GUILayout.EndArea();
    GUI.EndGroup();
    

GUILayoutOption 布局选项

  • 用法:作为 GUILayout.ButtonGUILayout.Label 等方法的可变参数传入才生效;单独写一行 GUILayout.Width(300) 而不传给控件,不会产生布局效果。
  • GUILayout.Width, GUILayout.Height:固定宽高。
  • GUILayout.MinWidth, GUILayout.MinHeight:最小宽高。
  • GUILayout.MaxWidth, GUILayout.MaxHeight:最大宽高。
  • GUILayout.ExpandWidth, GUILayout.ExpandHeight:允许或禁止在对应方向上把剩余空间吃满。

12.3 面试题精选

基础题

1. Unity 里的 GUI 与 IMGUI 是什么关系,常见用在哪

题目

篇中如何定义 GUI / IMGUI?列举三类主要用途,并说明作者明确不建议的使用场景。

深入解析
  • 定义:GUI 即 IMGUI(即时模式、代码驱动);Unity 里常直接叫 GUI。
  • 用途:游戏内调试工具;脚本自定义检视面板;编辑器窗口与扩展 Unity 的内置工具。
  • 禁忌:不要为玩家制作正式 UI 功能(交付界面应交给更合适的 UI 技术栈)。
答题示例

这里的 GUI 就是 IMGUI,用代码即时描述界面。

典型用在 Debug 面板、自定义 Inspector、编辑器工具;不适合做给玩家的成品界面。

参考文章
  • 2.工作原理和主要作用

2. Button 和 RepeatButton 什么时候为 true

题目

GUI.Button 怎样才算点到一次?GUI.RepeatButton 按住不放时一直为 true 吗,指针移出控件会怎样?

深入解析
  • Button:在控件范围内完成一次有效的按下—抬起组合才在抬起当帧得到 true;按下与抬起若跨区域组合,篇中明确说不会得到 true
  • RepeatButton:按住且指针仍在控件内时持续 true;按住过程中移出矩形,立刻变为 false
答题示例

Button 要在按钮里按下并正常完成一次点击才 true,内外混按不算。

RepeatButton 按住在内才一直 true,拖出范围马上 false。

参考文章
  • 3.基础控件-文本和按钮控件

3. 设置了 GUI.skin 为什么有的按钮还是不走皮肤

题目

篇中示例里,先 GUI.skin = mySkin,为什么有的 GUI.Button 仍然表现为自定义 GUIStyle,而不是皮肤里的默认按钮样式?

深入解析
  • 控件调用里显式传入 GUIStyle 参数时,以该样式为准,当前 GUI.skin 不会覆盖这次绘制。
  • 只有未单独指定 GUIStyle 的那类调用,才会吃到 GUI.skin 里配置的默认样式。
答题示例

传了 GUIStyle 的那次 Button 用参数样式,不吃全局 skin。

没传 GUIStyle 的才用当前 GUI.skin 的默认外观。

参考文章
  • 10.自定义整体样式-自定义皮肤样式

进阶题

1. OnGUI 的回调节奏与生命周期位置

题目

篇中对 OnGUI 的执行频率、在生命周期中的相对顺序有什么结论?写 OnGUI 时应遵守什么书写习惯?

深入解析
  • 频率:每帧执行,专门承担 GUI 绘制与交互入口的角色。
  • 顺序:位于 LateUpdate 之后、OnDisable 之前。
  • 习惯:回调里以 GUI 绘制与界面相关逻辑为主,避免塞无关重逻辑,便于维护和排查。
答题示例

OnGUI 每帧跑,在 LateUpdate 后、OnDisable 前。

里面主要写画界面和处理按钮这类 GUI 逻辑,别当通用 Update 用。

参考文章
  • 2.工作原理和主要作用

2. BeginScrollView 三个矩形和 scroll 向量各自干什么

题目

GUI.BeginScrollView 的视口矩形、传入的 scrollPositionviewRect 分别控制什么?为什么代码里常见 nowPos = GUI.BeginScrollView(..., nowPos, ...) 必须把返回值赋回去?

深入解析
  • 视口矩形:滚动视图在屏幕上的可见区域(含滚动条区域)。
  • scrollPosition:内容相对视口的偏移,引擎根据交互改它,不取返回值写回变量则下一帧状态对不上
  • viewRect:内容逻辑尺寸;小于视口不出现滚动,大于视口才需要拖滚动条;动态列表常按条目数乘行高调整高度。
答题示例

外面那个 Rect 是视口,viewRect 是整块内容有多大,scroll 是内容挪了多少。

BeginScrollView 会改滚动偏移,必须赋回字段或变量,不然滚不动或乱跳。

参考文章
  • 8.组合控件-滚动视图和分组

3. GUILayout 适合干什么,和 GUI.BeginGroup 怎么配合

题目

按课文,GUILayout 主要适合哪类工作?示例里 BeginGroupBeginAreaBeginVertical / BeginHorizontal 大致是什么包含关系?

深入解析
  • 课文把 GUILayout 定位在编辑器向自动排版;与手写 RectGUI 相比,少抠坐标,但不等于能替代 UGUI 等玩家界面方案。
  • 结构上:先用 GUI.BeginGroup 圈总区域,再用 GUILayout.BeginArea 在组内划自动布局画布,竖直或水平组再往里排控件;EndVertical / EndHorizontalEndAreaEndGroup 依次配对弹出。
答题示例

GUILayout 适合编辑器里省 Rect,课文说不适合扛正式游戏 UI。

Group 包大块,Area 里再竖直或水平排控件,End 顺序和 Begin 反着关。

参考文章
  • 11.自定义整体样式-自动布局

深度题

1. 为什么不宜用 IMGUI 做玩家正式界面

题目

结合篇中「三条主要用途 + 一条注意」,从定位上说明为什么 IMGUI 更适合工具链与调试,而不是玩家可见的正式 UI。

深入解析
  • 原文把能力圈在调试、Inspector、编辑器扩展,并单独强调不要服务玩家 UI,说明其设计重心在研发与工具链,而不是玩家可见的正式界面。
  • 立即模式、代码驱动意味着界面主要在脚本里逐帧描述;玩家向界面往往还要接美术资源、布局复用、多分辨率适配等工程需求,专用 UI 方案通常更合适。
  • 工程上玩家 UI 常见 UGUI、UI Toolkit 等,把 IMGUI 留在 Debug、Inspector、Editor 扩展更符合原文定位。
答题示例

文章把 GUI 用在 Debug、Inspector、编辑器工具,并写明别给玩家做 UI。

它是给开发和工具用的即时绘制;玩家界面要走资源与布局更成熟的 UI 系统,否则维护和适配成本不划算。

参考文章
  • 2.工作原理和主要作用

2. 可拖动窗口为什么要用成员 Rect 接 Window 返回值

题目

IMGUI 里做可拖窗口时,为什么通常把窗口矩形存成字段,并写 dragWinPos = GUI.Window(id, dragWinPos, DrawWindow, title)GUI.DragWindow 写在哪儿、无参和有参 Rect 各是什么效果?

深入解析
  • 拖动会改变窗口位置,必须把每帧算出的新矩形保存到成员里,下一帧才能接着从正确位置画。
  • DragWindow 只在窗口绘制回调里调用才生效;无参表示整窗可拖,带 Rect 时只有该区域作为拖动手柄(例如标题栏高度一条)。
答题示例

位置会变就要存字段里,每帧用 Window 返回值更新。

DragWindow 写在窗口函数里;不传 Rect 全窗能拖,传了 Rect 只有那块区域能拖。

参考文章
  • 9.组合控件-窗口相关

3. 换 GUISkin 前为什么先把三种颜色设回白色

题目

课文在 GUI.skin = mySkin 之前把 GUI.colorGUI.contentColorGUI.backgroundColor 都设成白色,这和「颜色相乘」有什么关系?若跳过这一步可能出现什么现象?

深入解析
  • contentColorbackgroundColor 会与 GUI.color 相乘作用到最终绘制;上一轮若把全局色留在红、黄、绿等状态,再套新皮肤等于整皮被旧 tint 染一层
  • 先归零到白色再换 skin,才能较接近资源里设计好的 GUISkin 观感,排查样式问题时也少一层干扰。
答题示例

三种颜色是相乘关系,不先设白,旧的全局着色会染在新皮肤上。

先全部 white 再 GUI.skin,看到的才接近皮肤资源本身。

参考文章
  • 10.自定义整体样式-自定义皮肤样式


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏