程序框架——UI管理模块
UI基类BasePanel
负责帮助我们通过代码快速的找到所有的子控件,方便我们在子类中处理逻辑,节约找控件的工作量。
public class BasePanel : MonoBehaviour
{//通过里式转换原则 来存储所有的控件private Dictionary<string, List<UIBehaviour>> controlDic = new Dictionary<string, List<UIBehaviour>>();// Use this for initializationprotected virtual void Awake () {FindChildrenControl<Button>();FindChildrenControl<Image>();FindChildrenControl<Text>();FindChildrenControl<Toggle>();FindChildrenControl<Slider>();FindChildrenControl<ScrollRect>();FindChildrenControl<InputField>();}/// <summary>/// 显示自己/// </summary>public virtual void ShowMe(){}/// <summary>/// 隐藏自己/// </summary>public virtual void HideMe(){}protected virtual void OnClick(string btnName){}protected virtual void OnValueChanged(string toggleName, bool value){}/// <summary>/// 得到对应名字的对应控件脚本/// </summary>/// <typeparam name="T"></typeparam>/// <param name="controlName"></param>/// <returns></returns>protected T GetControl<T>(string controlName) where T : UIBehaviour{if(controlDic.ContainsKey(controlName)){for( int i = 0; i <controlDic[controlName].Count; ++i ){if (controlDic[controlName][i] is T)return controlDic[controlName][i] as T;}}return null;}/// <summary>/// 找到子对象的对应控件/// </summary>/// <typeparam name="T"></typeparam>private void FindChildrenControl<T>() where T:UIBehaviour{T[] controls = this.GetComponentsInChildren<T>();for (int i = 0; i < controls.Length; ++i){string objName = controls[i].gameObject.name;if (controlDic.ContainsKey(objName))controlDic[objName].Add(controls[i]);elsecontrolDic.Add(objName, new List<UIBehaviour>() { controls[i] });//如果是按钮控件if(controls[i] is Button){(controls[i] as Button).onClick.AddListener(()=>{OnClick(objName);});}//如果是单选框或者多选框else if(controls[i] is Toggle){(controls[i] as Toggle).onValueChanged.AddListener((value) =>{OnValueChanged(objName, value);});}}}
}
UI管理模块UIManager
管理所有显示的面板,提供给外部 显示和隐藏等等方法。
/// <summary>
/// UI层级
/// </summary>
public enum E_UI_Layer
{Bot,Mid,Top,System,
}/// <summary>
/// UI管理器
/// 1.管理所有显示的面板
/// 2.提供给外部 显示和隐藏等等接口
/// </summary>
public class UIManager : BaseManager<UIManager>
{public Dictionary<string, BasePanel> panelDic = new Dictionary<string, BasePanel>();private Transform bot;private Transform mid;private Transform top;private Transform system;//记录我们UI的Canvas父对象 方便以后外部可能会使用它public RectTransform canvas;public UIManager(){//创建Canvas 让其过场景的时候 不被移除GameObject obj = ResMgr.GetInstance().Load<GameObject>("UI/Canvas");canvas = obj.transform as RectTransform;GameObject.DontDestroyOnLoad(obj);//找到各层bot = canvas.Find("Bot");mid = canvas.Find("Mid");top = canvas.Find("Top");system = canvas.Find("System");//创建EventSystem 让其过场景的时候 不被移除obj = ResMgr.GetInstance().Load<GameObject>("UI/EventSystem");GameObject.DontDestroyOnLoad(obj);}/// <summary>/// 通过层级枚举 得到对应层级的父对象/// </summary>/// <param name="layer"></param>/// <returns></returns>public Transform GetLayerFather(E_UI_Layer layer){switch(layer){case E_UI_Layer.Bot:return this.bot;case E_UI_Layer.Mid:return this.mid;case E_UI_Layer.Top:return this.top;case E_UI_Layer.System:return this.system;}return null;}/// <summary>/// 显示面板/// </summary>/// <typeparam name="T">面板脚本类型</typeparam>/// <param name="panelName">面板名</param>/// <param name="layer">显示在哪一层</param>/// <param name="callBack">当面板预设体创建成功后 你想做的事</param>public void ShowPanel<T>(string panelName, E_UI_Layer layer = E_UI_Layer.Mid, UnityAction<T> callBack = null) where T:BasePanel{if (panelDic.ContainsKey(panelName)){panelDic[panelName].ShowMe();// 处理面板创建完成后的逻辑if (callBack != null)callBack(panelDic[panelName] as T);//避免面板重复加载 如果存在该面板 即直接显示 调用回调函数后 直接return 不再处理后面的异步加载逻辑return;}ResMgr.GetInstance().LoadAsync<GameObject>("UI/" + panelName, (obj) =>{//把他作为 Canvas的子对象//并且 要设置它的相对位置//找到父对象 你到底显示在哪一层Transform father = bot;switch(layer){case E_UI_Layer.Mid:father = mid;break;case E_UI_Layer.Top:father = top;break;case E_UI_Layer.System:father = system;break;}//设置父对象 设置相对位置和大小obj.transform.SetParent(father);obj.transform.localPosition = Vector3.zero;obj.transform.localScale = Vector3.one;(obj.transform as RectTransform).offsetMax = Vector2.zero;(obj.transform as RectTransform).offsetMin = Vector2.zero;//得到预设体身上的面板脚本T panel = obj.GetComponent<T>();// 处理面板创建完成后的逻辑if (callBack != null)callBack(panel);panel.ShowMe();//把面板存起来panelDic.Add(panelName, panel);});}/// <summary>/// 隐藏面板/// </summary>/// <param name="panelName"></param>public void HidePanel(string panelName){if(panelDic.ContainsKey(panelName)){panelDic[panelName].HideMe();GameObject.Destroy(panelDic[panelName].gameObject);panelDic.Remove(panelName);}}/// <summary>/// 得到某一个已经显示的面板 方便外部使用/// </summary>public T GetPanel<T>(string name) where T:BasePanel{if (panelDic.ContainsKey(name))return panelDic[name] as T;return null;}/// <summary>/// 给控件添加自定义事件监听/// </summary>/// <param name="control">控件对象</param>/// <param name="type">事件类型</param>/// <param name="callBack">事件的响应函数</param>public static void AddCustomEventListener(UIBehaviour control, EventTriggerType type, UnityAction<BaseEventData> callBack){EventTrigger trigger = control.GetComponent<EventTrigger>();if (trigger == null)trigger = control.gameObject.AddComponent<EventTrigger>();EventTrigger.Entry entry = new EventTrigger.Entry();entry.eventID = type;entry.callback.AddListener(callBack);trigger.triggers.Add(entry);}}
-
测试代码
public class LoginPanel : BasePanel
{public void InitData() {Debug.Log("初始化信息!");}// Start is called before the first frame updatevoid Start(){//GetControl<Button>("btnLogin").onClick.AddListener(()=> {// Debug.Log("我被点击了");//});// GetControl<Button>("btnExit").onClick.AddListener(()=> {// Debug.Log("我要退出了");// this.gameObject.SetActive(false);// });UIManager.AddCustomEventListener(GetControl<Button>("btnExit"), EventTriggerType.PointerEnter, (data) =>{Debug.Log("我要进入了");});UIManager.AddCustomEventListener(GetControl<Button>("btnExit"), EventTriggerType.PointerExit, (data) =>{Debug.Log("我要退出了");});}protected override void OnClick(string btnName){switch (btnName){case "btnLogin":Debug.Log("我被点击了");break;case "btnExit":Debug.Log("我要退出了");break;default:break;}}public override void ShowMe(){Debug.Log("我显示出来了!");}public override void HideMe(){Debug.Log("我要隐藏了!");}// Update is called once per framevoid Update(){}
}
public class UITest : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){UIManager.GetInstance().ShowPanel<LoginPanel>("LoginPanel", E_UI_Layer.Mid, showPanel);}void showPanel(LoginPanel loginPanel){loginPanel.InitData();}// Update is called once per framevoid Update(){}
}相关文章:
程序框架——UI管理模块
UI基类BasePanel 负责帮助我们通过代码快速的找到所有的子控件,方便我们在子类中处理逻辑,节约找控件的工作量。 public class BasePanel : MonoBehaviour {//通过里式转换原则 来存储所有的控件private Dictionary<string, List<UIBehaviour>…...
MySQL 慢查询探究分析
目录 背景: mysql 整体结构: SQL查询语句执行过程是怎样的: 知道了mysql的整体架构,那么一条查询语句是怎么被执行的呢: 什么是索引: 建立索引越多越好吗: 如何发现慢查询࿱…...
wpf 项目中使用 Prism + MaterialDesign
1.通过nuget安装MaterialDesign 2.通过nuget安装Prism 3.修改App.xmal <prism:PrismApplication x:Class"VisionMeasureGlue.App"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/…...
【Spring Boot】Thymeleaf模板引擎 — Thymeleaf页面布局
Thymeleaf页面布局 熟悉Thymeleaf的语法和表达式后,后面开发起来会更加得心应手。接下来好好研究一下Thymeleaf如何实现完整的Web系统页面布局。 1.引入代码片段 在模板中经常希望包含来自其他模板页面的内容,如页脚、页眉、菜单等。为了做到这一点&a…...
整理mongodb文档:删
个人博客 整理mongodb文档:删 求关注,哪儿不足,求大佬们指出,哪儿写的不够通俗易懂跟清晰,也求指出 文章概叙 本文主要是介绍了删除数据的几个方法,主要还是在介绍deleteMany、deleteOne以及remove,对于…...
篇二十三:设计模式的综合实例:构建完整项目
篇二十三:"设计模式的综合实例:构建完整项目" 开始本篇文章之前先推荐一个好用的学习工具,AIRIght,借助于AI助手工具,学习事半功倍。欢迎访问:http://airight.fun/。 另外有2本不错的关于设计模…...
FFmpeg常见命令行(三):FFmpeg转码
前言 在Android音视频开发中,网上知识点过于零碎,自学起来难度非常大,不过音视频大牛Jhuster提出了《Android 音视频从入门到提高 - 任务列表》。本文是Android音视频任务列表的其中一个, 对应的要学习的内容是:如何使…...
合宙Air724UG LuatOS-Air script lib API--scanCode
Table of Contents scanCode scanCode.request(cbFnc, timeout) scanCode 模块功能:扫码. 支持二维码、条形码扫描 scanCode.request(cbFnc, timeout) 设置扫码请求 参数 名称 传入值类型 释义 cbFnc function 扫码返回或者超时未返回的回调函数,回调…...
2023年新手如何学剪辑视频 想学视频剪辑如何入门
随着短视频、vlog等媒体形式的兴起,视频剪辑已经成为了热门技能。甚至有人说,不会修图可以,但不能不会剪视频。实际上,随着各种智能软件的发展,视频剪辑已经变得越来越简单。接下来,一起来看看新手如何学剪…...
C++的auto究竟是何方神圣
C的auto究竟是何方神圣 前言🙌auto(C 11) 的使用细则auto是什么? auto声明的变量是在什么时期被编译器推导出来呢?为什么使用auto进行定义变量时,必须进行初始化? auto 的使用场景auto与指针和引…...
网络安全【黑客】面试题汇总
前言 一眨眼2023年已经过去一大半,不知道大家有没有找到心仪的工作。作为一个安全老鸟,工作这么多年,面试过很多人也出过很多面试题目,也在网上收集了各类关于渗透面试题目,里面有我对一些问题的见解,希望…...
docker菜谱大全
记录docker常用软件安装,感谢小马哥和杨师傅的投稿。😎😎😎 相关文档: DockerHub:https://hub.docker.com/Linux手册:https://linuxcool.com/Docker文档:https://docs.docker.com/Do…...
git: git checkout命令
git checkout 命令在Git中有不同的用法和功能,具体取决于您在命令后面提供的参数。以下是一些常见的用法: 1. 切换分支:您可以使用 git checkout <branch> 切换到指定的分支。例如,要切换到名为 "feature-branch"…...
以游戏编程的角度看待模拟时间的算法题——以PAT甲级1026 Table Tennis为例
对于需要模拟时间的算法题,可以将开始时间作为游戏的开始(如Unity的Start或UE的BeginPlay),每一秒的模拟作为游戏的画面更新(如Unity的Update或UE的Tick),结束时间可作为游戏的结束(…...
SNAT与DNAT原理
SNAT和DNAT (源地址转换和目标地址转换) SNAT:源地址转换。内网到外网转换的是源地址。 DNAT:目标地址转换:外网到内网转换的是目的地址 (把内部服务器的ip地址转换成一个所有人都可以访问的地址࿰…...
04-2_Qt 5.9 C++开发指南_SpinBox使用
文章目录 1. SpinBox简介2. SpinBox使用2.1 可视化UI设计2.2 widget.h2.3 widget.cpp 1. SpinBox简介 QSpinBox 用于整数的显示和输入,一般显示十进制数,也可以显示二进制、十六进制的数,而且可以在显示框中增加前缀或后缀。 QDoubleSpinBox…...
接口安全防护方案
文章目录 1.认证与授权机制2.参数校验3.接口加密4.防止暴力破解5.安全头设置6.日志监控 1.认证与授权机制 使用令牌(Token)、OAuth等认证方式,确保只有合法用户可以访问接口。授权机制可以防止未经授权的用户访问敏感接口。 示例:…...
机器学习复习题
1 单选题 ID3算法、C4.5算法、CART算法都是( )研究方向的算法。 A . 决策树 B. 随机森林 C. 人工神经网络 D. 贝叶斯学习 参考答案:A ( )作为机器学习重要算法之一,是一种利用多个树分类器进行分类和预测…...
无线液位传感器—简介
近年来,随着无线传感网络技术的愈发成熟和稳定,无线传感器因其安装、维护方便,不用布线、节约成本,监测方便,使用灵活,可适用于多种工业领域等优点,正在逐步替代部分传统有线传感器,…...
通讯协议034——全网独有的OPC HDA知识一之聚合(三)时间加权平均
本文简单介绍OPC HDA规范的基本概念,更多通信资源请登录网信智汇(wangxinzhihui.com)。 本节旨在详细说明HDA聚合的要求和性能。其目的是使HDA聚合标准化,以便HDA客户端能够可靠地预测聚合计算的结果并理解其含义。如果用户需要聚合中的自定义功能&…...
【Python原生AOT编译终极蓝图】:2026架构设计图首次解密,3大不可逆技术拐点已至
第一章:Python原生AOT编译2026架构全景概览Python原生AOT(Ahead-of-Time)编译在2026年已演进为一套融合语言语义、运行时契约与硬件感知能力的统一基础设施。其核心目标是消除解释器开销、保障启动确定性、支持无依赖二进制分发,并…...
终极指南:五分钟让Win11老游戏重获联机能力的完整解决方案
终极指南:五分钟让Win11老游戏重获联机能力的完整解决方案 【免费下载链接】ipxwrapper 项目地址: https://gitcode.com/gh_mirrors/ip/ipxwrapper 还在为Win11系统下无法联机玩《星际争霸》《魔兽争霸2》《暗黑破坏神》等经典游戏而烦恼吗?今天…...
从理论到实践:百川2-13B模型权重加载与推理过程代码解读
从理论到实践:百川2-13B模型权重加载与推理过程代码解读 你是不是也遇到过这种情况:好不容易找到一个开源大模型,比如百川2-13B,兴冲冲地下载下来,结果面对那一堆模型权重文件和复杂的代码,瞬间就懵了&…...
CMB2前端集成教程:将元框和表单带到网站前台
CMB2前端集成教程:将元框和表单带到网站前台 【免费下载链接】CMB2 CMB2 is a developers toolkit for building metaboxes, custom fields, and forms for WordPress that will blow your mind. 项目地址: https://gitcode.com/gh_mirrors/cm/CMB2 想要在Wo…...
m4s-converter:让B站缓存重获新生的轻量级格式转换工具
m4s-converter:让B站缓存重获新生的轻量级格式转换工具 【免费下载链接】m4s-converter 一个跨平台小工具,将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 当你辛苦缓存的B站视频因下架…...
黑丝空姐-造相Z-Turbo场景应用:为你的内容创作提供无限灵感
黑丝空姐-造相Z-Turbo场景应用:为你的内容创作提供无限灵感 1. 镜像概述与核心能力 黑丝空姐-造相Z-Turbo是一款基于Xinference部署的文生图模型服务,通过gradio提供直观的交互界面。该镜像专注于生成特定风格的视觉内容,为创意工作者提供高…...
基于Qwen3-ASR的智能会议纪要系统:从语音识别到文本摘要全流程
基于Qwen3-ASR的智能会议纪要系统:从语音识别到文本摘要全流程 1. 系统整体效果展示 今天给大家展示一个基于Qwen3-ASR-1.7B语音识别模型构建的智能会议纪要系统。这个系统不仅能准确识别会议中的语音内容,还能自动区分不同说话人,提取关键…...
芯片研发为什么总是延期?问题不在技术,在管理没闭环
一个芯片项目失败,事后复盘,技术问题往往只占一小部分。更多的时候,是计划没做好,执行过程没人盯,出了问题没人协调,最后交付的时候才发现跑偏了很久。这是行业里非常普遍的现象。法约尔在一百年前提出管理…...
3步构建智能文献管理系统:Zotero GPT插件从配置到精通指南
3步构建智能文献管理系统:Zotero GPT插件从配置到精通指南 【免费下载链接】zotero-gpt GPT Meet Zotero. 项目地址: https://gitcode.com/gh_mirrors/zo/zotero-gpt 在信息爆炸的学术环境中,研究人员平均每天需要处理超过20篇文献,传…...
深度学习篇---全局平均池化(Global Average Pooling, GAP)
全局平均池化是深度学习中一个优雅而强大的操作,它通过极简的设计解决了全连接层参数量爆炸的问题,同时增强了模型的泛化能力。 一、什么是全局平均池化? 1. 基本定义 全局平均池化是对每个特征通道的所有空间位置取平均值,将三…...
