2025GUI工程实践:Unity编辑模式下GUI运行

news/2025/9/27 21:27:16/文章来源:https://www.cnblogs.com/wzzkaifa/p/19115693

一、需求分析

二、九宫格布局

三、空间位置信息类

1.对齐方式枚举(E_Alignment_Type)

2.核心属性

3.位置计算核心逻辑

步骤 1:计算控件中心点偏移(CalcCenterPos)

步骤 2:计算屏幕坐标位置(CalcPos)

4.最终位置获取

四、控件基类设计

1.样式开关枚举(E_Style_OnOff)

2.自定义 GUI 控件基类(CustomGUIControl)

(1)核心属性

(2)核心方法

3.自定义位置计算类(CustomGUIPos)

五、编辑模式GUI实时预览和显示顺序

1. 编辑模式实时预览

2.显示顺序控制

六、自定义按钮控件(CustomGUIButton)

1.按钮控件的核心特性

2.按钮控件的使用方法

七、自定义标签控件(CustomGUILabel)

1.标签控件的核心特性

2.标签控件的应用场景

八、自定义复选框控件

1.代码实现

2.控件核心特性解析

(1)状态管理

(2)事件机制

(3)样式支持

九、自定义ToggleGroup 单选框控件

1.代码实现

2.实现原理解析

(1)核心功能

(2)数组管理

(3)事件监听

(4)互斥逻辑

(5)至少一项选中

十、自定义输入框控件(CustomGUIInput)

1.代码实现

2.输入框控件核心特性

十一、自定义滑动条控件(CustomGUISlider)


一、需求分析


二、九宫格布局


三、空间位置信息类

1.对齐方式枚举(E_Alignment_Type)

        定义了 9 种基础对齐方式,覆盖了屏幕和控件的所有关键位置。

public enum E_Alignment_Type
{Up,          // 上中Down,        // 下中Left,        // 左中Right,       // 右中Center,      // 中心Left_Up,     // 左上Left_Down,   // 左下Right_Up,    // 右上Right_Down   // 右下
}

这些枚举值用于描述两个关键对齐关系:
(1)控件相对于屏幕的对齐方式
(2)控件自身中心点的对齐方式

2.核心属性

属性作用
screen_Alignment_Type控件相对于屏幕的九宫格对齐方式
control_Center_Alignment_Type控件自身的中心点对齐方式
pos基于对齐点的偏移位置
width/height控件的宽高
Pos(只读属性)计算后最终用于绘制的 Rect 位置

3.位置计算核心逻辑

步骤 1:计算控件中心点偏移(CalcCenterPos)

        根据控件自身的对齐方式,计算控件左上角相对于其对齐点的偏移量:

private void CalcCenterPos()
{switch (control_Center_Alignment_Type){case E_Alignment_Type.Up:centerPos.x = -width / 2;  // 水平居中centerPos.y = 0;           // 顶部对齐break;// 其他对齐方式的计算...}
}
步骤 2:计算屏幕坐标位置(CalcPos)

        根据屏幕对齐方式,结合屏幕分辨率和偏移量,计算控件在屏幕上的最终位置:

private void CalcPos()
{switch (screen_Alignment_Type){case E_Alignment_Type.Up:// 屏幕上中位置 + 控件偏移 + 自定义偏移rPos.x = Screen.width/2 + centerPos.x + pos.x;rPos.y = 0 + centerPos.y + pos.y;break;// 其他屏幕对齐方式的计算...}
}

4.最终位置获取

        通过Pos属性将计算逻辑封装,外部使用时无需关心内部计算细节:

public Rect Pos
{get{CalcCenterPos();  // 先计算控件自身偏移CalcPos();        // 再计算屏幕位置rPos.width = width;rPos.height = height;return rPos;}
}


四、控件基类设计

1.样式开关枚举(E_Style_OnOff)

public enum E_Style_OnOff
{On,  // 使用自定义样式Off  // 使用默认样式
}

        用于控制控件是否启用自定义样式,提供了灵活的样式切换能力。

2.自定义 GUI 控件基类(CustomGUIControl)

        这是所有自定义控件的基类,继承自 MonoBehaviour,封装了控件的共性属性和行为。

(1)核心属性

属性作用
guiPos类型为CustomGUIPos,控制控件的位置和大小,实现自适应布局
content类型为GUIContent,存储控件的显示内容(文本、图片、提示等)
style类型为GUIStyle,存储自定义样式信息
styleOnOrOff类型为E_Style_OnOff,控制是否启用自定义样式

(2)核心方法

OnGUI():重写 MonoBehaviour 的生命周期方法,作为控件绘制的入口

private void OnGUI()
{switch (styleOnOrOff){case E_Style_OnOff.On:StyleOnDraw();  // 使用自定义样式绘制break;case E_Style_OnOff.Off:StyleOffDraw();  // 使用默认样式绘制break;}
}

StyleOnDraw():使用自定义样式绘制控件的虚方法

protected virtual void StyleOnDraw()
{// 子类需重写此方法实现具体绘制逻辑// 示例: GUI.Button(guiPos.Pos, content, style);
}

StyleOffDraw():使用默认样式绘制控件的虚方法

protected virtual void StyleOffDraw()
{// 子类需重写此方法实现具体绘制逻辑// 示例: GUI.Button(guiPos.Pos, content);
}

3.自定义位置计算类(CustomGUIPos)

        此类在之前基础上增加了[System.Serializable]特性,使其可以在 Inspector 面板中显示和编辑,极大提升了可视化编辑体验。

[System.Serializable]
public class CustomGUIPos
{// 保持原有功能实现...
}


五、编辑模式GUI实时预览和显示顺序

1. 编辑模式实时预览

        通过[ExecuteAlways]特性和特殊的更新逻辑,实现了编辑模式下的实时预览:

[ExecuteAlways]
public class CustomGUIRoot : MonoBehaviour
{// ...private void OnGUI(){// 编辑模式下每次绘制前更新控件列表if( !Application.isPlaying ){allControls = this.GetComponentsInChildren();}// ...}
}

        这使得开发者在编辑模式下无需进入 Play 状态,就能实时看到 GUI 效果,极大提升了开发效率。

2.显示顺序控制

        通过根控制器统一管理所有控件的绘制顺序,解决了传统 IMGUI 显示顺序混乱的问题:

// 按数组顺序绘制控件,控制显示层级
for (int i = 0; i < allControls.Length; i++)
{allControls[i].DrawGUI();
}

        数组中靠前的控件先绘制,靠后的控件后绘制(显示在上方),开发者可以通过调整数组顺序精确控制显示层级。


六、自定义按钮控件(CustomGUIButton)

        我们的自定义按钮实现了点击事件的封装,方便外部进行事件绑定。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class CustomGUIButton : CustomGUIControl
{// 提供给外部的按钮点击事件// 外部可通过绑定此事件响应按钮点击public event UnityAction clickEvent;// 重写默认样式绘制方法protected override void StyleOffDraw(){// 绘制按钮并检测点击if( GUI.Button(guiPos.Pos, content ) ){// 安全调用事件(如果有绑定事件处理函数则执行)clickEvent?.Invoke();}}// 重写自定义样式绘制方法protected override void StyleOnDraw(){// 使用自定义样式绘制按钮并检测点击if (GUI.Button(guiPos.Pos, content, style)){// 安全调用事件clickEvent?.Invoke();}}
}

1.按钮控件的核心特性

(1)事件驱动设计

  • 使用UnityAction定义点击事件,符合 Unity 的事件处理习惯
  • 通过clickEvent?.Invoke()实现事件的安全调用,避免空引用异常

(2)样式支持

  • 重写了基类的StyleOffDraw()StyleOnDraw()方法
  • 分别实现了默认样式和自定义样式的按钮绘制逻辑

(3)继承优势

  • 直接使用基类提供的guiPos属性实现自适应位置
  • 利用基类的content属性管理显示内容(文本、图片等)
  • 自动支持样式开关切换功能

2.按钮控件的使用方法

// 获取按钮控件实例
CustomGUIButton myButton = GetComponent();
// 绑定点击事件
myButton.clickEvent += OnButtonClicked;
// 事件处理函数
private void OnButtonClicked()
{Debug.Log("按钮被点击了!");
}


七、自定义标签控件(CustomGUILabel)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CustomGUILabel : CustomGUIControl
{// 重写默认样式绘制方法protected override void StyleOffDraw(){GUI.Label(guiPos.Pos, content);}// 重写自定义样式绘制方法protected override void StyleOnDraw(){GUI.Label(guiPos.Pos, content, style);}
}

1.标签控件的核心特性

(1)简洁实现

  • 仅重写了绘制方法,没有额外的属性和逻辑
  • 专注于文本和图片的展示功能

(2)样式支持

  • 同样实现了默认样式和自定义样式两种绘制方式
  • 可通过GUIStyle自定义字体、颜色、对齐方式等

(3)内容灵活性

  • 利用GUIContent类型的content属性,支持:
    • 纯文本显示
    • 纯图片显示
    • 文本 + 图片组合显示
    • 包含提示信息(tooltip)的显示

2.标签控件的应用场景

  • 显示标题和说明文字
  • 展示状态信息(如生命值、分数等)
  • 显示图片或图标
  • 作为界面布局的辅助元素


八、自定义复选框控件

1.代码实现

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class CustomGUIToggle : CustomGUIControl
{// 复选框当前选中状态public bool isSel;// 状态变化事件,传递新的状态值public event UnityAction changeValue;// 用于记录上一帧的状态,检测状态变化private bool isOldSel;// 重写默认样式绘制方法protected override void StyleOffDraw(){// 绘制复选框并更新状态isSel = GUI.Toggle(guiPos.Pos, isSel, content);// 仅在状态发生变化时通知外部if(isOldSel != isSel){changeValue?.Invoke(isSel);isOldSel = isSel;}}// 重写自定义样式绘制方法protected override void StyleOnDraw(){// 使用自定义样式绘制复选框并更新状态isSel = GUI.Toggle(guiPos.Pos, isSel, content, style);// 仅在状态发生变化时通知外部if (isOldSel != isSel){changeValue?.Invoke(isSel);isOldSel = isSel;}}
}

2.控件核心特性解析

(1)状态管理

  • 当前状态:通过isSel变量存储复选框的当前选中状态(true为选中,false为未选中)
  • 状态追踪:使用isOldSel变量记录上一帧的状态,用于检测状态是否发生变化
  • 状态更新:每次绘制时通过GUI.Toggle方法自动更新isSel的值

(2)事件机制

  • 事件定义:使用UnityAction<bool>类型的changeValue事件,当状态变化时会将新状态作为参数传递
  • 触发时机:仅在状态实际发生变化时才触发事件,避免不必要的性能消耗
  • 安全调用:使用changeValue?.Invoke(isSel)语法,确保在没有绑定事件处理函数时不会抛出空引用异常

(3)样式支持

  • 继承基类的样式管理机制,支持两种绘制模式:
    • StyleOffDraw():使用默认样式绘制
    • StyleOnDraw():使用自定义GUIStyle绘制
  • 两种模式下都保持相同的状态检测和事件触发逻辑,确保行为一致性


九、自定义ToggleGroup 单选框控件

1.代码实现

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CustomGUIToggleGroup : MonoBehaviour
{// 存储需要管理的所有Toggle控件public CustomGUIToggle[] toggles;// 记录上一次选中的Toggleprivate CustomGUIToggle frontTurTog;void Start(){if (toggles.Length == 0)return;// 为每个Toggle添加状态变化事件监听for (int i = 0; i < toggles.Length; i++){CustomGUIToggle toggle = toggles[i];toggle.changeValue += (value) =>{// 当某个Toggle被选中时if( value ){// 将其他所有Toggle设为未选中for (int j = 0; j < toggles.Length; j++){if( toggles[j] != toggle ){toggles[j].isSel = false;}}// 更新上一次选中的Toggle记录frontTurTog = toggle;}// 当试图取消当前选中的Toggle时else if( toggle == frontTurTog){// 强制保持选中状态(至少保留一个选中项)toggle.isSel = true;}};}}
}

2.实现原理解析

(1)核心功能

CustomGUIToggleGroup的核心作用是管理一组CustomGUIToggle控件,确保同一时间只有一个 Toggle 处于选中状态,实现单选功能。

(2)数组管理

  • 通过public CustomGUIToggle[] toggles数组存储需要管理的所有 Toggle 控件
  • 在 Inspector 面板中手动指定需要纳入管理的 Toggle 控件

(3)事件监听

  • Start()方法中为每个 Toggle 绑定changeValue事件
  • 使用 Lambda 表达式处理状态变化逻辑,简洁高效

(4)互斥逻辑

  • 当某个 Toggle 被选中(value 为 true)时,遍历所有 Toggle,将其他 Toggle 设为未选中
  • 使用frontTurTog变量记录当前选中的 Toggle,确保状态一致性

(5)至少一项选中

  • 当试图取消当前唯一选中的 Toggle 时,强制保持其选中状态
  • 避免出现所有选项都未选中的情况(可根据需求修改此逻辑)


十、自定义输入框控件(CustomGUIInput)

1.代码实现

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class CustomGUIInput : CustomGUIControl
{// 文本变化事件,传递旧文本值public event UnityAction textChange;// 用于记录上一次的文本值,检测变化private string oldStr = "";// 重写默认样式绘制方法protected override void StyleOffDraw(){// 绘制输入框并更新内容content.text = GUI.TextField(guiPos.Pos, content.text);// 仅在文本实际变化时触发事件if(oldStr != content.text){textChange?.Invoke(oldStr);oldStr = content.text;}}// 重写自定义样式绘制方法protected override void StyleOnDraw(){// 使用自定义样式绘制输入框并更新内容content.text = GUI.TextField(guiPos.Pos, content.text, style);// 仅在文本实际变化时触发事件if (oldStr != content.text){textChange?.Invoke(oldStr);oldStr = content.text;}}
}

2.输入框控件核心特性

文本管理

  • 利用基类的content.text存储输入的文本内容
  • 通过GUI.TextField实现文本输入功能

变化检测

  • 使用oldStr记录上一帧的文本值
  • 仅在文本实际发生变化时触发事件,避免不必要的性能消耗

事件机制

  • 定义textChange事件,在文本变化时通知外部
  • 事件参数传递旧文本值,方便对比前后变化

样式支持

  • 同时支持默认样式和自定义样式
  • 保持与其他控件一致的样式切换机制


十一、自定义滑动条控件(CustomGUISlider)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public enum E_Slider_Type
{Horizontal,  // 水平滑动条Vertical     // 垂直滑动条
}
public class CustomGUISlider : CustomGUIControl
{// 最小值public float minValue = 0;// 最大值public float maxValue = 1;// 当前值public float nowValue = 0;// 滑动条方向类型public E_Slider_Type type = E_Slider_Type.Horizontal;// 滑块的自定义样式public GUIStyle styleThumb;// 数值变化事件public event UnityAction changeValue;// 用于记录上一次的数值,检测变化private float oldValue = 0;// 重写默认样式绘制方法protected override void StyleOffDraw(){// 根据类型绘制不同方向的滑动条switch (type){case E_Slider_Type.Horizontal:nowValue = GUI.HorizontalSlider(guiPos.Pos, nowValue, minValue, maxValue);break;case E_Slider_Type.Vertical:nowValue = GUI.VerticalSlider(guiPos.Pos, nowValue, minValue, maxValue);break;}// 仅在数值实际变化时触发事件if(oldValue != nowValue){changeValue?.Invoke(nowValue);oldValue = nowValue;}}// 重写自定义样式绘制方法protected override void StyleOnDraw(){// 使用自定义样式绘制不同方向的滑动条switch (type){case E_Slider_Type.Horizontal:nowValue = GUI.HorizontalSlider(guiPos.Pos, nowValue, minValue, maxValue, style, styleThumb);break;case E_Slider_Type.Vertical:nowValue = GUI.VerticalSlider(guiPos.Pos, nowValue, minValue, maxValue, style, styleThumb);break;}// 仅在数值实际变化时触发事件if (oldValue != nowValue){changeValue?.Invoke(nowValue);oldValue = nowValue;}}
}

方向支持

  • 通过E_Slider_Type枚举支持水平和垂直两种方向
  • 根据方向自动选择对应的绘制方法(HorizontalSlider/VerticalSlider

数值范围

  • 通过minValuemaxValue定义数值范围
  • nowValue存储当前选中的数值,始终保持在范围内

样式定制

  • 支持轨道(style)和滑块(styleThumb)的分别样式定制
  • 提供更精细的视觉效果控制

变化检测

  • 使用oldValue记录上一帧的数值
  • 仅在数值实际变化时触发事件,优化性能

事件机制

  • 定义changeValue事件,传递当前数值
  • 方便外部系统响应数值变化

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/919960.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最好的wordpress 网站wordpress 验证密码错误

B站UP主实时数据展示系统 - PHP源码分享 想要实时追踪你心仪的B站UP主的最新动态吗&#xff1f;现在&#xff0c;你可以轻松获取并展示B站UP主的实时数据&#xff0c;包括粉丝数、作品数、头像、播放量等关键信息。 功能亮点&#xff1a; 实时更新&#xff1a;系统通过B站AP…

网站关键词排名优化工具昆明做一个公司网站多少费用

解题思路&#xff1a; 递归参数&#xff1a; 生成括号的对数 n、结果集 result、当前路径 path、左括号数 open、右括号数 close。递归过程&#xff1a; 当当前路径 path 的长度等于 n * 2 时&#xff0c;说明已经生成有效括号&#xff0c;加入结果集。若左括号数小于 n&…

哦好多天没写了水一下吧

哦好多天没写了水一下吧这几天虽然没写,但是一直在干,跟着教程已经干到第三步了,现在在干第四步,发现我的博客完全是没营养的东西。。。。。。。。。。。。。。。。。。。。。。。。。。。

wordpress做网站建设部住房城乡建设厅网站

Bilibili助手&#xff0c;一款非常精彩的手机B站助手软件。通过这款应用你可以轻松实现自动领取礼物、自动签到、自动领经验等功能&#xff0c;非常精彩 &#xff0c;赶紧下载试试吧&#xff01;Bilibili助手介绍Bilibili助手&#xff0c;第二简单的助手&#xff0c;简单、便捷…

专门做ppt的网站wordpress views插件

Linux中sudo、su和su -命令的区别小结 我们知道&#xff0c;在Linux下对很多文件进行修改都需要有root&#xff08;管理员&#xff09;权限&#xff0c;比如对/ect/profile等文件的修改。下面这篇文章主要给大家总结介绍了关于Linux中sudo、su和su -命令的区别的相关资料&…

实用指南:Apache、Nginx 和 Tomcat 的区别

实用指南:Apache、Nginx 和 Tomcat 的区别pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "…

python+uniapp基于微信小程序美食点餐实用的系统

python+uniapp基于微信小程序美食点餐实用的系统pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", …

parted command for linuxg

安装parted yum install -y parted 列出现有磁盘分区 parted -l检查磁盘状态(sda是新添加的磁盘) parted /dev/sda print新建磁盘分区表类型MBR parted -s /dev/sda mklabel msdos 新建磁盘分区表类型gpt parted -s …

如何在不绑定Apple账号的情况下备份florr.io

很多入像我一样,喜欢玩florr.io 可是只能在同一个电脑的一个浏览器上玩一个账号,换电脑或浏览器的时候就只能含着泪,告别账号 但是你可以绑定 \(Apple\) 账号,到别的电脑或浏览器时登录账号 虽然能备份账号,但这个…

深圳店铺设计优化培训内容

数据库的三级模式两级映射: 存储文件------>基本表----->视图 内模式 ------->模式 ------>外模式 一、视图 1、什么是视图: 视图是从一个或多个表中导出来的表,是一种虚拟存在的表。 视图就像一个窗口,通过这个窗口可以看到系统专门提供的数据。 这样,用…

AI智能体框架怎么选?7个主流工具详细对比解析

大语言模型(LLM)虽然拥有强大的理解和生成能力,但本质上还只是一个能够处理文本的模型,并且它们无法主动获取信息、执行操作或与外部系统交互。 而AI智能体可以通过为LLM配备工具调用、环境感知和自主决策能力,将…

原创OI试题 - L

T1 换乘(metro) 题目背景 H3Z信息科学协会成员准备参加NOIP。他们准备从学校出发,乘坐地铁到达考场。但是,地铁线网错综复杂,换乘次数带来的问题困扰住了LzyCoding。作为信息科学协会的一名成员,你能写个程序来帮帮…

《深入浅出WPF》:8.3.2 自定义路由事件 事件注册类型为 EventHandlerReportTimeEventArgs,但.NET 事件包装器类型为 RoutedEventHandler

事件处理器的签名要和注册时的签名一致:包装器的参数类型为基类型,事件处理器的参数类型为子类型,根据委托协变,可以把子类型参数的委托赋值给基类型参数的委托以下是deepseek回答: 这是一个非常好的问题,它触及…

网站转app工具高级版怎么分析网站建设的优缺点

Pytorch torchvision 包提供了很多常用数据集 数据按照用途一般分为三组&#xff1a;训练&#xff08;train&#xff09;、验证&#xff08;validation&#xff09;和测试&#xff08;test&#xff09;。使用训练数据集来训练模型&#xff0c;使用验证数据集跟踪模型在训练期间…

2025 自动售货机工厂推荐 配备 Bystronic 激光切割机,快速周转准时交货

在自动售货机生产领域,选择实力过硬的工厂是保障产品品质与合作效率的关键。2025 年,想要找到配备先进设备、拥有专业团队且能稳定交付的自动售货机工厂,东吉智能设备有限公司无疑是值得重点关注的选择。东吉智能设…

完整教程:探索 12 种 3D 文件格式:综合指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

完整教程:配送跑腿系统:构建高并发、低延迟的同城配送系统架构解析

完整教程:配送跑腿系统:构建高并发、低延迟的同城配送系统架构解析2025-09-27 21:05 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto …

网站建设与管理专业的行业发展惠州seo排名收费

场景在开发中我们经常需要对图片以人脸为中心进行剪切并显示&#xff0c;这时就需要下面这个工具了。实现效果实现效果项目参考及引用项目使用将下载的jar 和 .so 文件加入到项目中。API 说明在项目中使用如下API即可&#xff1a;CImageView这是一个继承ImageView的图片控件&am…

2019年云南建设银行招聘网站福建龙岩有哪些网络平台

问题&#xff1a; 在文件读取&#xff0c;判断md5值时&#xff0c;遇到py文件读取转String后&#xff0c;再转byte&#xff0c;md5前后不一致问题。 解决方法&#xff1a; python文件读取要使用QTextStream&#xff0c;避免\t 、\r、\n的换行符跨平台问题&#xff08;window…

自己做网站 需要会什么6做网站

Python中的collections模块 文章目录 Python中的collections模块1.Counter对象2.deque对象3.defaultdict对象4.namedtuple5.OrderedDictReference Python中的 collections提供许多容器数据类型&#xff0c;这个模块实现了一些专门化的容器&#xff0c;提供了对Python的通用内建…