Unity的UI框架

news/2024/5/21 14:00:23/文章来源:https://blog.csdn.net/ht_game/article/details/125273548

UI框架

UI框架的含义

含义:UI框架用于管理场景中所有的面板,负责控制面板之间的跳转

UI框架的意义

1、随着游戏系统的复杂化,UI控件越来越多,各个UI之间的直接通讯,已经UI与GameObject之间的关系会越来越复杂
2、代码耦合性会很强

UI框架的实例

1、框架面板的设计

MainMenuPanel:主菜单面板
BagPanel:背包面板
ItemMessagePanel:物品信息面板
ShopPanel:商城面板
SkillPanel:技能面板
SystemPanel:系统面板
TaskPanel:技能面板

在这里插入图片描述
我们将设计好的面板做成预制体,放在Resources的目录下。

2、Json数据的读取

UIPanelInfo.json

{"infoList":[{"panelTypeString": "ItemMessage","path": "UIPanel/ItemMessagePanel"},{"panelTypeString": "BagPanel","path": "UIPanel/BagPanel"},{"panelTypeString": "MainMenu","path": "UIPanel/MainMenuPanel"},{"panelTypeString": "Shop","path": "UIPanel/ShopPanel"},{"panelTypeString": "Skill","path": "UIPanel/SkillPanel"},{"panelTypeString": "System","path": "UIPanel/SystemPanel"},{"panelTypeString": "Task","path": "UIPanel/TaskPanel"}]
}
将所有信息作为一个infolist类的对象

UIPanelType

public enum UIPanelType 
{BagPanel,ItemMessage,MainMenu,Shop,Skill,System,Task,
}

UIManager

public class UIManager 
{private Dictionary<UIPanelType, string> panelPathDicr;//存储所有面板Prefab的路径,UIPanelType类型,string用于存储路径private UIManager(){ParseUIPanelTypeJson();//调用ParseUIPanelTypeJson方法解析Json文件}//单例化private static UIManager instance;public static UIManager GetInstance(){if (instance == null){instance = new UIManager();}return instance;}[Serializable]class UIPanelTypeJson//将Json文件视作一个整体,直接将其转换为List<UIPanelInfo>{public List<UIPanelInfo> infoList;}//解析Json文件private void ParseUIPanelTypeJson(){panelPathDicr = new Dictionary<UIPanelType, string>();//生成一个字典TextAsset ta = Resources.Load<TextAsset>("UIPanelType");//加载Json文件中的UIPanelType信息UIPanelTypeJson jsonObject = JsonUtility.FromJson<UIPanelTypeJson>(ta.text);//JsonUtility——工具类,将Json中的文件解析为对象,ta.text就是JSON信息,将JSON信息转换为UIPanelTypeJson类//总的意思就是将JSON文件转换为UIPanelTypeJson类,而UIPanelTypeJson类中则是List<UIPanelInfo>,并其字段infoList对应JSON文件的类名foreach (UIPanelInfo info in jsonObject.infoList)//遍历UIPanelInfo的数组{//Debug.Log(info.panelType);panelPathDicr.Add(info.panelType, info.path);//这里的info相对于生成一个jsonObject.infoList,因此info就是数组中的一个元素。//将对象加入到字典当中去}}public void Test()//测试{string path;panelPathDicr.TryGetValue(UIPanelType.Shop, out path);Debug.Log(path);}
}

UIPanelInfo

[Serializable]
public class UIPanelInfo:ISerializationCallbackReceiver//将UIPanelInfo进行序列化,[Serializable]标签就是运行下面字段可进行读盘和写盘,负责与Json文件向对应,读取Json的文件,传递数据,可以避免直接修改Json文件
{[NonSerialized]public UIPanelType panelType;//记录Json文件中的panelType对象//由于无法直接解析UIPanelType,所有使用string来接受Json数据public string panelTypeString;//{第一种方式转换方式。//    get//    {//        return panelType.ToString();//    }//    set //    {//      UIPanelType type = (UIPanelType)System.Enum.Parse(typeof(UIPanelType), value);//        panelType = type;//    }//}public string path;//记录path的路径字段//反序列化 从文本信息到对象public void OnAfterDeserialize()//每次反序列化后就会调用{UIPanelType type = (UIPanelType)System.Enum.Parse(typeof(UIPanelType), panelTypeString);panelType = type;//将文本中的panelTypeString强制转换成UIPanelType}public void OnBeforeSerialize()//每次序列化之前调用这个方法{}
}
分析:
首先
1、UIPanelType类
作为一个枚举类,用于记录各个面板,保存面板的类型
2、UIPanelType.json
这是一个Json文件,用于存储各个面板的具体信息
例如:"panelTypeString": "MainMenu","path": "UIPanel/MainMenuPanel"
panelTypeString保存对象
path保存路径
3、UIPanelInfo
负责与Json文件向对应public UIPanelType panelType;//记录Json文件中的panelType对象public string path;//记录path的路径字段这里要将其设置为可序列化的状态[Serializable],让这个类可以读盘与写盘,方便后期对信息进行修改
,也可以避免直接修改Json文件
4、UIManger
是UI框架的核心,负责管理各种框架
第一步,将其设置为单例模式
第二步,将Json文件解析
第三步,使用UIPanelInfo的数组来接受Json文件的信息
第四步,遍历UIPanelInfo数组,并将其中的数据加入字典当中其中有两个关键点。
第一,加载Json文件,并将文件解析为UIPanelInfo对象的数组
第二,遍历数组,并加入字典中,方便以后对其数据进行各种操作

3、框架逻辑设计

在这里插入图片描述
BasePanel的设计

public class BasePanel : MonoBehaviour
{/// <summary>/// 界面被显示出来/// </summary>public virtual void OnEnter(){ }/// <summary>/// 界面暂停/// </summary>public virtual void OnPause(){ }/// <summary>/// 界面继续/// </summary>public virtual void OnResume(){ }/// <summary>/// 界面不显示,退出这个界面,界面被关闭/// </summary>public virtual void OnExit(){ }}

BagPanel继承BasePanel

public class BagPanel:BasePanel
{private CanvasGroup canvasGroup;private void Start(){if (canvasGroup == null){canvasGroup = GetComponent<CanvasGroup>();}}/// <summary>/// 处理页面的关闭/// </summary>public override void OnExit(){// canvasGroup.alpha = 0;canvasGroup.blocksRaycasts = false;transform.DOLocalMoveX(600, 0.5f).OnComplete(() => canvasGroup.alpha = 0);}public void OnClosePanel(){UIManager.GetInstance().PopPanel();}public override void OnEnter(){if (canvasGroup == null){canvasGroup = GetComponent<CanvasGroup>();}canvasGroup.alpha = 1;canvasGroup.blocksRaycasts = true;//弹出动画Vector3 temp = transform.localPosition;temp.x = 600;transform.localPosition = temp;transform.DOLocalMoveX(0, 0.5f);}public override void OnPause(){canvasGroup.blocksRaycasts = false;}public override void OnResume(){canvasGroup.blocksRaycasts = true;}public void OnItemButtonClick(){UIManager.GetInstance().PushPanel(UIPanelType.ItemMessage);}
}

完善后的UIManager

public class UIManager 
{private Transform canvasTransform;private Transform CanvasTransform{get {if (canvasTransform == null){canvasTransform = GameObject.Find("Canvas").transform;}return canvasTransform;}}private Dictionary<UIPanelType, string> panelPathDicr;//存储所有面板Prefab的路径,UIPanelType类型,string用于存储路径private Dictionary<UIPanelType, BasePanel> panelDict;//保存所有面板的游戏物体身上的BasePanel组件private Stack<BasePanel> panelStacks;/// <summary>/// 把某个页面入栈,触发相应方法,并显示在界面上/// </summary>public void PushPanel(UIPanelType panelType){if (panelStacks == null){panelStacks = new Stack<BasePanel>();}//判断一下栈里面是否有页面if (panelStacks.Count > 0){BasePanel topPanel = panelStacks.Peek();topPanel.OnPause();}BasePanel panel = GetPanel(panelType);panel.OnEnter();panelStacks.Push(panel);}/// <summary>/// 出栈,把页面从界面上移除/// </summary>public void PopPanel(){if (panelStacks == null){panelStacks = new Stack<BasePanel>();}//BasePanel panel = GetPanel(panelType);if (panelStacks.Count <= 0){return;}BasePanel topPanel = panelStacks.Pop();topPanel.OnExit();if (panelStacks.Count <= 0) return;BasePanel topPanel2 = panelStacks.Peek();topPanel2.OnResume();}/// <summary>/// 根据面板类型,得到实例化的面板/// </summary>/// <returns></returns>public BasePanel GetPanel(UIPanelType panelType){if (panelDict == null){panelDict = new Dictionary<UIPanelType, BasePanel>();}//BasePanel panel;//panelDict.TryGetValue(panelType, out panel);//TODOBasePanel panel = panelDict.TryGet(panelType);if (panel == null){//如果找不到,就找这个面板的Prefab的路径,然后去根据Prefab去实例化面板//string path;//panelPathDicr.TryGetValue(panelType, out path);string path = panelPathDicr.TryGet(panelType);//字典对象的值是已经决定了的,所以不需要使用泛型而dict对象就是panelPathDicr,不需要再赋值字典var pan = Resources.Load(path);GameObject instPanel = GameObject.Instantiate(pan) as GameObject;//实例化instPanel.transform.SetParent(CanvasTransform, false);//TODO false表示局部位置,而非全局位置panelDict.Add(panelType, instPanel.GetComponent<BasePanel>());return instPanel.GetComponent<BasePanel>();}else{return panel;}}private UIManager(){ParseUIPanelTypeJson();//调用ParseUIPanelTypeJson方法解析Json文件}//单例化private static UIManager instance;public static UIManager GetInstance(){if (instance == null){instance = new UIManager();}return instance;}[Serializable]class UIPanelTypeJson//将Json文件视作一个整体,直接将其转换为List<UIPanelInfo>{public List<UIPanelInfo> infoList;}//解析Json文件private void ParseUIPanelTypeJson(){panelPathDicr = new Dictionary<UIPanelType, string>();//生成一个字典TextAsset ta = Resources.Load<TextAsset>("UIPanelType");//加载Json文件中的UIPanelType信息UIPanelTypeJson jsonObject = JsonUtility.FromJson<UIPanelTypeJson>(ta.text);//JsonUtility——工具类,将Json中的文件解析为对象,ta.text就是JSON信息,将JSON信息转换为UIPanelTypeJson类//总的意思就是将JSON文件转换为UIPanelTypeJson类,而UIPanelTypeJson类中则是List<UIPanelInfo>,并其字段infoList对应JSON文件的类名foreach (UIPanelInfo info in jsonObject.infoList)//遍历UIPanelInfo的数组{//Debug.Log(info.panelType);panelPathDicr.Add(info.panelType, info.path);//这里的info相对于生成一个jsonObject.infoList,因此info就是数组中的一个元素。//将对象加入到字典当中去}}public void Test()//测试{string path;panelPathDicr.TryGetValue(UIPanelType.Shop, out path);Debug.Log(path);}
}
分析
1、BasePanel作为基类被其他的具体类继承
而BasePanel中的方法为OnEnter()——进入OnPause()——暂停OnResume()——恢复OnExit()——退出2、具体的类在继承的基础上,进行具体的修改,添加事件3、UIManager则负责使用“栈”来对不同页面进行管理

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

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

相关文章

盘点一个Python自动化办公的实战案例

点击上方“Python共享之家”&#xff0c;进行关注回复“资源”即可获赠Python学习资料今日鸡汤岭猿同旦暮&#xff0c;江柳共风烟。大家好&#xff0c;我是皮皮。 一、前言前几天在Python钻石交流群【Hxy任我肥】问了一个Python自动化办公的问题&#xff0c;提问截图如下&am…

基于Vue+SSM+SpringCloudAlibaba的英雄管理系统

需求 前端技术&#xff1a;element-ui、vue后端技术&#xff1a;spring boot、spring cloud、mybatis plus、jwt项目要求&#xff1a; 前端&#xff1a;exam-war-fore-1217后端&#xff1a;exam-war-parent-1217端口要求&#xff1a; 注册中心&#xff1a;10086、10087 &#x…

福特、微软、槟榔-《软件方法》自测题解析019

DDD领域驱动设计批评文集>> 《软件方法》强化自测题集>> 《软件方法》各章合集>> 《软件方法》第2章自测题2 1 [单选题] 1999年11月的《财富》杂志题为“20世纪企业家”的文章&#xff0c;评选出了最能代表20世纪企业家精神的企业家─福特汽车的Henry F…

云原生|kubernetes|ingress-nginx插件部署以及简单的应用

前言&#xff1a; ingress直译&#xff1a;进口&#xff1b;入口&#xff1b;初切&#xff1b;进入&#xff1b;进入资格&#xff1b;进入权。在kubernetes中&#xff0c;它指的是网络入口。 ingress概述&#xff1a; 通俗来讲&#xff0c;Ingress和之前提到的Service、Depl…

Redis面试汇总笔记

在两个月前的学习中&#xff0c;我看过一个redis相关的讲解视频&#xff0c;是一个叫诸葛的老师&#xff0c;其中分为几层进行讲述&#xff0c;分别是数据类型、分布式锁、redis常见问题等。当时有记录一些内容&#xff0c;下面将按照顺序进行分享。 &#xff08;一&#xff0…

Cherno的Cpp教程笔记002:C++是如何工作的

include需要找到一个叫iostream的文件&#xff0c;然后将内容拷贝到当前的文件中来 main函数是程序的入口&#xff0c;main中调用了std::cout , main函数不一定需要返回值&#xff0c;当没有返回值时默认返回0 #include是预处理语句&#xff0c;编译器优先处理这些语句&#…

橘子学Mybatis03之代理模式

一、什么是代理模式&#xff0c;为啥需要代理模式 1、问题 在JAVAEE的MVC分层开发中&#xff0c;哪个层级对我们来说最重要&#xff1f; DAO ------> Service --------> ControllerJAVAEE分层开发中&#xff0c;最为重要的是Service层。这个也可以理解&#xff0c;因为S…

Lesson 8 The best and the worst 最好的和最差的

1.原文 2. 参考译文 3. New words and expressions ★competition n. 比赛&#xff0c;竞赛(暗地里的竞争) race n. 比赛&#xff0c;竞赛 car racematch n. 比赛 football matchcontest n. 比赛(更广泛)baby contest 宝宝大赛&#xff1b;beauty contest 选美game : 游戏, 运…

Spring自学日志01-IOC(控制翻转)

目录一、IOC的基本概念和底层原理1.1、什么是IOC?1.1.1、Spring IOC容器1.2、IOC底层原理1.2.1、IOC容器1.2.2、IOC容器装配Bean的方式1.2.3、IOC容器装配Bean的操作1.2.3.1、基于XML1.2.3.2、基于注解1.2.4、IOC容器装配Bean的作用域 一、IOC的基本概念和底层原理 1.1、什么是…

MySQL:索引特性

索引 0. 预备知识 索引是一个“物美价廉”的特性&#xff0c;用来提高数据库的性能。不需要改程序、调SQL、只需要正确的创建索引&#xff0c;查询速度就能提高成百上千倍&#xff0c;但查询速度的提升也带来了插入、更新、删除速度的下降。 0.1 认识磁盘 MySQL对数据进行增…

大数据讲课笔记2.1 初探大数据

文章目录零、学习目标一、导入新课二、新课讲解&#xff08;一&#xff09;什么是大数据&#xff08;二&#xff09;大数据的特征1、数据体量大2、数据类型多3、处理速度快4、价值密度低&#xff08;三&#xff09;研究大数据的意义&#xff08;四&#xff09;拥抱大数据时代1、…

【数据结构初阶】第四话 —— 动态栈的基本操作

文章目录什么是栈栈的结构1. 初始化栈2. 入栈3. 出栈4. 获取栈顶元素5. 获取栈中有效元素个数6. 检测栈是否为空7. 销毁栈8. 总结接口函数贴图什么是栈 假如有⼀个⼜细⼜⻓的圆筒&#xff0c;圆筒⼀端封闭&#xff0c;另⼀端开⼝。往圆筒⾥放⼊乒乓球&#xff0c;先放⼊的靠近…

U盘插入自动读写/U盘插入自动复制/pythhttps://www.cnblogs.com/wawawa888/p/16749476.htmlon检测U盘的插入,以及进行自动复制文件并写入文件

U盘自动读写的小玩意 共有四种方法(我知道的方法,全是转载。转载也很不易,可望给个硬币) 方法一(vbs方法 全自动,转载自bilibili 点我跳转)文件下载链接(点我下载) 方法二(cmd方法 需手动,转载自bilibili 点我跳转)文件下载链接(点我下载) 方法三(python方法 全…

在DataFrame中根据索引值进行排序:sort_index()函数

【小白从小学Python、C、Java】 【Python-计算机等级考试二级】 【Python-数据分析】 在DataFrame中根据索引值进行排序&#xff1a; sort_index()函数 [太阳]选择题 对以下python代码表述有误的选项是&#xff1f; import numpy as np import pandas as pd data np.random.…

ElasticSearch_03_批量处理命令mget和bulk的使用

系列文章目录 文章目录系列文章目录前言一、批量处理命令mget方案1&#xff1a;body请求体中指定index和type方案2&#xff1a;url中指定index和type&#xff0c;body中仅指定ids方案2扩展&#xff1a;url中指定index和type&#xff0c;body中仅指定id数组二、基于bulk的增删改…

C++开发坦克大战--补充(加入传送门)--附完整代码

目录 素材整理 穿越草地 坦克穿越草地 子弹穿越草地 传送门 判定形式 生成传送门 传送坦克 关卡模式 效果展示 ​总结 完整代码 上一篇坦克大战居然意外获得了一些关注&#xff0c;正好最近也完善了一些功能&#xff0c;同时也加入了一些自己想到的新元素&#xff0c;主要是…

python requests cookie的获取和使用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、cookie是什么&#xff1f;二、使用步骤开始代码实现会话是什么然后写入我们的账号信息使用session访问登陆账号的url获取账号的书架上的数据完整的代码补充比…

基于javaweb在线投票管理系统ssm

基于SSM的在线投票系统以XXX学院为背景&#xff0c;运用在校所学习的软件开发原理&#xff0c;采用SpringSpringMVCMyBatis技术和MySQL数据库构建一个基于B/S模式的在线投票系统。 传统的投票模式都是通过人工手动填写问卷的方式来进行&#xff0c;这在很大程度上会造成人力和…

1.1 Ryu 的安装部署

What is Ryu Ryu是轻量级的、开源的SDN控制器Ryu是由日本NTT公司在2012年推出其名字在日文中的意思是“Flow”和“Dragon”的意思 Ryu架构 Ryu安装 在Ubuntu上装Ryu和Mininet&#xff0c;CSDN上搜教程&#xff0c;这一部分正确做法是对着视频敲代码如果有问题去CSDN上找解决办…

滤波器基础01——滤波器的种类与特性

滤波器是一种选频装置&#xff0c;它能够保留某一频段的信号&#xff0c;将此频段之外的信号消除。以下介绍不同分类依据下滤波器的特点。 一. 模拟滤波器与数字滤波器 根据滤波器的作用对象是模拟信号还是数字信号可将滤波器分为模拟滤波器和数字滤波器。 模拟滤波器处理模…