【GameFramework框架内置模块】18、界面(UI)

推荐阅读

  • CSDN主页
  • GitHub开源地址
  • Unity3D插件分享
  • 简书地址
  • QQ群:398291828

大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。

一、前言

【GameFramework框架】系列教程目录:
https://blog.csdn.net/q764424567/article/details/135831551

二、正文

2-1、介绍

界面(UI)提供管理UI界面和界面组的功能,比如显示界面、激活界面、改变界面层级等。

界面(UI)为Unity的GUI系统提供了灵活和强大的功能,帮助开发者快速构建游戏UI。

还可以与现有的Unity 的UI插件(如NGUI、FGUI)及GUI系统(UGUI)无缝集成,只要派生自UIFormLogic类并实现自己的界面类即可使用。

界面使用结束后可以不立即销毁,等待下一次使用。

2-2、使用说明

(1)UIComponent组件的编辑器面板

在这里插入图片描述
UIComponent组件的编辑器面板,配置UI的回调事件、UI界面组、界面对象池参数,以及辅助器的设置。

UIGroups
UI界面的管理,层级的管理是不可少的,而UIGroups就是处理不同页面的层级。

在同一个Group中可以打开不同的页面。

不同的Group组中的UI的层级不一样的,比如UI我们可以这么分:

  • Scene层:最底层,场景UI,一般置于场景之上,界面UI之下,如:点击建筑查看建筑信息—
  • Background层:背景UI,如:主界面,一般情况下用户不能主动关闭,永远处于其它Ul的最底层
  • Normal层:普通UI,一级、二级、三级等窗口,一般由用户点击打开的多级窗口
  • lnfo层:信息UI,—如:跑马灯、广播等,—般永远置于用户打开窗口顶层
  • Tip层:提示UI,如:错误弹窗,网络连接弹窗等
  • Top层:顶层UI,如:场景加载
(2)配置UI界面配置表

配置表
在这里插入图片描述
界面配置表中配置了UI界面Id、资源名AssetName、UI组名UIGroupName、是否允许多个实例allow multiple instances,以及是否覆盖UIForm。

预制体
在这里插入图片描述

参数及枚举

这些参数的设置,可以保证框架在打开UI界面时可以找到UI界面的相关参数。

在UIFormId.cs中,添加枚举,注意枚举的Id要和配置表的id一致:

namespace StarForce
{/// <summary>/// 界面编号。/// </summary>public enum UIFormId : byte{Undefined = 0,/// <summary>/// 弹出框。/// </summary>DialogForm = 1,/// <summary>/// 主菜单。/// </summary>MenuForm = 100,/// <summary>/// 设置。/// </summary>SettingForm = 101,/// <summary>/// 关于。/// </summary>AboutForm = 102,}
}
(3)打开、获取、关闭UI界面

UI的相关操作,代码示例如下:

//打开
GameEntry.UI.OpenUIForm(UIFormId.MenuForm);
//获取
GameEntry.UI.GetUIForm(UIFormId.MenuForm);
//关闭
GameEntry.UI.CloseUIForm(uiForm);

这里只说明如何打开UI,具体UI的加载过程将在下一节详细分析。

(4)传递参数

打开UI传参数数组,或者自己指定实体类。

传参:

GameEntry.UI.OpenUIForm(UIFormId.MainForm, new object[]{xxx,xxx});

UI界面接收参数:

public class MenuForm : UGuiForm
{protected override void OnOpen(object userData){base.OnOpen(userData);var args = (object[])userData;//......}
}
(5)实现UI界面的事件

MenuForm.cs为例,继承UGuiForm后,实现UI事件即可:

using UnityEngine;
using UnityGameFramework.Runtime;namespace StarForce
{public class MenuForm : UGuiForm{[SerializeField]private GameObject m_QuitButton = null;private ProcedureMenu m_ProcedureMenu = null;public void OnStartButtonClick(){m_ProcedureMenu.StartGame();}public void OnSettingButtonClick(){GameEntry.UI.OpenUIForm(UIFormId.SettingForm);}public void OnAboutButtonClick(){GameEntry.UI.OpenUIForm(UIFormId.AboutForm);}public void OnQuitButtonClick(){GameEntry.UI.OpenDialog(new DialogParams(){Mode = 2,Title = GameEntry.Localization.GetString("AskQuitGame.Title"),Message = GameEntry.Localization.GetString("AskQuitGame.Message"),OnClickConfirm = delegate (object userData) { UnityGameFramework.Runtime.GameEntry.Shutdown(ShutdownType.Quit); },});}#if UNITY_2017_3_OR_NEWERprotected override void OnOpen(object userData)
#elseprotected internal override void OnOpen(object userData)
#endif{base.OnOpen(userData);m_ProcedureMenu = (ProcedureMenu)userData;if (m_ProcedureMenu == null){Log.Warning("ProcedureMenu is invalid when open MenuForm.");return;}m_QuitButton.SetActive(Application.platform != RuntimePlatform.IPhonePlayer);}#if UNITY_2017_3_OR_NEWERprotected override void OnClose(bool isShutdown, object userData)
#elseprotected internal override void OnClose(bool isShutdown, object userData)
#endif{m_ProcedureMenu = null;base.OnClose(isShutdown, userData);}}
}

绑定事件:
在这里插入图片描述

2-3、实现及代码分析

接下来,就来分析一下GameFramework框架,在GameEntry.UI.OpenUIForm(UIFormId.MenuForm)中做了那些事情吧。

(1)打开UI界面过程及代码分析

打开UI界面:

GameEntry.UI.OpenUIForm(UIFormId.MenuForm, this);

获取数据表中的数据传递给uiComponent.OpenUIForm()函数:

public static int? OpenUIForm(this UIComponent uiComponent, UIFormId uiFormId, object userData = null)
{return uiComponent.OpenUIForm((int)uiFormId, userData);
}public static int? OpenUIForm(this UIComponent uiComponent, int uiFormId, object userData = null)
{IDataTable<DRUIForm> dtUIForm = GameEntry.DataTable.GetDataTable<DRUIForm>();DRUIForm drUIForm = dtUIForm.GetDataRow(uiFormId);if (drUIForm == null){Log.Warning("Can not load UI form '{0}' from data table.", uiFormId.ToString());return null;}string assetName = AssetUtility.GetUIFormAsset(drUIForm.AssetName);if (!drUIForm.AllowMultiInstance){if (uiComponent.IsLoadingUIForm(assetName)){return null;}if (uiComponent.HasUIForm(assetName)){return null;}}return uiComponent.OpenUIForm(assetName, drUIForm.UIGroupName, Constant.AssetPriority.UIFormAsset, drUIForm.PauseCoveredUIForm, userData);
}

资源路径的获取:

string assetName = AssetUtility.GetUIFormAsset(drUIForm.AssetName);
// 获取到预制体的路径
public static string GetUIFormAsset(string assetName)
{return Utility.Text.Format("Assets/GameMain/UI/UIForms/{0}.prefab", assetName);
}

调用UIComponent组件封装的m_UIManager的API:

/// <summary>
/// 打开界面。
/// </summary>
/// <param name="uiFormAssetName">界面资源名称。</param>
/// <param name="uiGroupName">界面组名称。</param>
/// <param name="priority">加载界面资源的优先级。</param>
/// <param name="pauseCoveredUIForm">是否暂停被覆盖的界面。</param>
/// <param name="userData">用户自定义数据。</param>
/// <returns>界面的序列编号。</returns>
public int OpenUIForm(string uiFormAssetName, string uiGroupName, int priority, bool pauseCoveredUIForm, object userData)
{return m_UIManager.OpenUIForm(uiFormAssetName, uiGroupName, priority, pauseCoveredUIForm, userData);
}

OK,最后一步了属于是,我们找到UIManager.cs脚本来看一下:

/// <summary>
/// 打开界面。
/// </summary>
/// <param name="uiFormAssetName">界面资源名称。</param>
/// <param name="uiGroupName">界面组名称。</param>
/// <param name="priority">加载界面资源的优先级。</param>
/// <param name="pauseCoveredUIForm">是否暂停被覆盖的界面。</param>
/// <param name="userData">用户自定义数据。</param>
/// <returns>界面的序列编号。</returns>
public int OpenUIForm(string uiFormAssetName, string uiGroupName, int priority, bool pauseCoveredUIForm, object userData)
{if (m_ResourceManager == null){throw new GameFrameworkException("You must set resource manager first.");}if (m_UIFormHelper == null){throw new GameFrameworkException("You must set UI form helper first.");}if (string.IsNullOrEmpty(uiFormAssetName)){throw new GameFrameworkException("UI form asset name is invalid.");}if (string.IsNullOrEmpty(uiGroupName)){throw new GameFrameworkException("UI group name is invalid.");}UIGroup uiGroup = (UIGroup)GetUIGroup(uiGroupName);if (uiGroup == null){throw new GameFrameworkException(Utility.Text.Format("UI group '{0}' is not exist.", uiGroupName));}int serialId = ++m_Serial;UIFormInstanceObject uiFormInstanceObject = m_InstancePool.Spawn(uiFormAssetName);if (uiFormInstanceObject == null){m_UIFormsBeingLoaded.Add(serialId, uiFormAssetName);m_ResourceManager.LoadAsset(uiFormAssetName, priority, m_LoadAssetCallbacks, OpenUIFormInfo.Create(serialId, uiGroup, pauseCoveredUIForm, userData));}else{InternalOpenUIForm(serialId, uiFormAssetName, uiGroup, uiFormInstanceObject.Target, pauseCoveredUIForm, false, 0f, userData);}return serialId;
}

最后,判断是否存在这个UI界面的实例,有的话加载,没有的话通过Resource模块进行加载。

害!最后还得是Resource模块进行加载。

(2)UIManager.cs

UlManager类是整个UI框架的总管理器,负责UI的所有调度,如打开,关闭,激活等。

  • UIManager使用了ResourceManager来加载界面预制体资源等,所以UI框架只支持异步加载,不能同步打开UI界面或传参。
  • UIManager使用了ObjectPool来处理UI界面的复用和回收。让我们完全不用担心UI界面的垃圾处理问题,大胆放心的使用UI框架。
  • UIManager使用了Group组的方式类存储和维护UI界面,非常方便我们管理和扩展界面功能。
  • UIFormHelper是处理界面实例化,初始化和释放的辅助器,方便我们在实际使用时扩展UlManager
namespace GameFramework.UI
{/// 界面管理器。internal sealed partial class UIManager : GameFrameworkModule, IUIManager{private readonly Dictionary<string, UIGroup> m_UIGroups;//UI界面组private IResourceManager m_ResourceManager;//资源管理器private IObjectPool<UIFormInstanceObject> m_InstancePool;//界面实例对象池private IUIFormHelper m_UIFormHelper;//界面辅助器Helper/// 增加界面组。public bool AddUIGroup(string uiGroupName, int uiGroupDepth, IUIGroupHelper uiGroupHelper)/// 打开界面。public int OpenUIForm(string uiFormAssetName, string uiGroupName, object userData)/// 关闭界面public void CloseUIForm(IUIForm uiForm)/// 初始化打开UIFormprivate void InternalOpenUIForm(int serialId, string uiFormAssetName, UIGroup uiGroup, object uiFormInstance, bool pauseCoveredUIForm, bool isNewInstance, float duration, object userData)/// 异步加载UI预制体回调private void LoadAssetSuccessCallback(string uiFormAssetName, object uiFormAsset, float duration, object userData)}
}
(4)UIForm、UIFormLogic、UGuiForm

每个单独的页面是一个UIForm,它继承自IUIForm:

/// <summary>
/// 界面。
/// </summary>
public sealed class UIForm : MonoBehaviour, IUIForm
{private UIFormLogic m_UIFormLogic;/// 获取界面逻辑。/// 界面回收。public void OnRecycle(){m_UIFormLogic.OnRecycle();}/// 界面打开。public void OnOpen(object userData){m_UIFormLogic.OnOpen(userData);}/// 界面关闭。public void OnClose(bool isShutdown, object userData){m_UIFormLogic.OnClose(isShutdown, userData);}/// 界面暂停。public void OnPause(){m_UIFormLogic.OnPause();}/// 界面暂停恢复。public void OnResume(){m_UIFormLogic.OnResume();}/// 界面遮挡。public void OnCover(){m_UIFormLogic.OnCover();}/// 界面遮挡恢复。public void OnReveal(){m_UIFormLogic.OnReveal();}/// 界面激活。public void OnRefocus(object userData){m_UIFormLogic.OnRefocus(userData);}
}

UIForm只是一个UI窗口,,所有的界面逻辑都写在UlFormLogic中。

不管是UGUI,NGUI还是FGUI等等,只要继承自UIFormLogic就可以了。

比如Starforce中的UGuiForm:

namespace StarForce
{public abstract class UGuiForm : UIFormLogic{protected Canvas m_CachedCanvas = null;protected CanvasGroup m_CanvasGroup = null;//自定义函数public void Close(bool ignoreFade)public void PlayUISound(int uiSoundId)public static void SetMainFont(Font mainFont)//生命周期函数protected override void OnInit(object userData)protected override void OnRecycle()protected override void OnOpen(object userData)protected override void OnClose(bool isShutdown, object userData)protected override void OnPause()protected override void OnResume()protected override void OnCover()protected override void OnReveal()protected override void OnRefocus(object userData)protected override void OnUpdate(float elapseSeconds, float realElapseSeconds)protected override void OnDepthChanged(int uiGroupDepth, int depthInUIGroup)}
}

我们可以根据UGuiFormLogic的结构来实现我们自己的NGuiFormLogic或者FGuiFormLogic等等。

三、后记

如果觉得本篇文章有用别忘了点个关注,关注不迷路,持续分享更多Unity干货文章。


你的点赞就是对博主的支持,有问题记得留言:

博主主页有联系方式。

博主还有跟多宝藏文章等待你的发掘哦:

专栏方向简介
Unity3D开发小游戏小游戏开发教程分享一些使用Unity3D引擎开发的小游戏,分享一些制作小游戏的教程。
Unity3D从入门到进阶入门从自学Unity中获取灵感,总结从零开始学习Unity的路线,有C#和Unity的知识。
Unity3D之UGUIUGUIUnity的UI系统UGUI全解析,从UGUI的基础控件开始讲起,然后将UGUI的原理,UGUI的使用全面教学。
Unity3D之读取数据文件读取使用Unity3D读取txt文档、json文档、xml文档、csv文档、Excel文档。
Unity3D之数据集合数据集合数组集合:数组、List、字典、堆栈、链表等数据集合知识分享。
Unity3D之VR/AR(虚拟仿真)开发虚拟仿真总结博主工作常见的虚拟仿真需求进行案例讲解。
Unity3D之插件插件主要分享在Unity开发中用到的一些插件使用方法,插件介绍等
Unity3D之日常开发日常记录主要是博主日常开发中用到的,用到的方法技巧,开发思路,代码分享等
Unity3D之日常BUG日常记录记录在使用Unity3D编辑器开发项目过程中,遇到的BUG和坑,让后来人可以有些参考。

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

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

相关文章

WebGIS开发应该从哪些方面做准备

工程化思想 环境配置项目构建npm&#xff1a;Node包管理器&#xff0c;是 JavaScript 运行时 Node.js 的默认程序包管理器。 https://www.freecodecamp.org/chinese/news/what-is-npm-a-node-package-manager-tutorial-for-beginners/新建一个前端工程项目&#xff1a;前端框…

在项目中数据库如何优化?【MySQL主从复制(创建一个从节点复制备份数据)】【数据库读写分离ShardingJDBC(主库写,从库读)】

MySQL主从复制 MySQL主从复制介绍MySQL复制过程分成三步&#xff1a;1). MySQL master 将数据变更写入二进制日志( binary log)2). slave将master的binary log拷贝到它的中继日志&#xff08;relay log&#xff09;3). slave重做中继日志中的事件&#xff0c;将数据变更反映它自…

Vue 02 组件、Vue CLI

Vue学习 Vue 0201 组件引入概念组件的两种编写形式① 非单文件组件基本使用使用细节组件嵌套组件本质 VueComponent重要的内置关系 ② 单文件组件 02 Vue CLI介绍 & 文档安装使用步骤脚手架结构render默认配置ref 属性props配置mixin配置项插件scoped 样式案例&#xff1a;…

MySQL将id相同的两行数据合并group_concat

MySQL将id相同的两行数据合并 group_concat这个函数能将相同的行组合起来&#xff0c;省老事了。 MySQL中group_concat函数 完整的语法如下&#xff1a; group_concat([DISTINCT] 要连接的字段 [Order BY ASC/DESC 排序字段] [Separator ‘分隔符’]) 1.基本查询 Sql代码 2.…

java Web会议信息管理系统 用eclipse定制开发mysql数据库BS模式java编程jdbc

一、源码特点 jsp 会议信息管理系统是一套完善的web设计系统&#xff0c;对理解JSP java SERLVET mvc编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,eclipse开发&#xff0c;数据库为Mysql5.0&am…

ActiveMQ-04如何搭建一个完美的ActiveMQ集群

集群架构是一个很大的话题&#xff0c;官网就给我们介绍了几种 客户端&#xff1a;队列消费者集群-Queue Consumer Clusters服务端&#xff1a;Broker集群 - Broker Clusters 静态发现动态发现 服务端&#xff1a;Master-Slave 主从集群 Shared File System Master SlaveJDBC …

力扣hot100:207. 课程表

这是一道拓扑排序问题&#xff0c;也可以使用DFS判断图中是否存在环。详情请见&#xff1a;官方的BFS算法请忽略&#xff0c;BFS将问题的实际意义给模糊了&#xff0c;不如用普通拓扑排序思想。 数据结构&#xff1a;图的拓扑排序与关键路径 拓扑排序&#xff1a; class Sol…

鸿蒙APP开发实战:【Api9】拍照、拍视频;选择图片、视频、文件工具类

鸿蒙开发过程中&#xff0c;经常会进行系统调用&#xff0c;拍照、拍视频、选择图库图片、选择图库视频、选择文件。今天就给大家分享一个工具类。 1. 话不多说&#xff0c;先展示样式 2.设计思路 根据官方提供的指南开发工具类&#xff0c;基础的拍照、拍视频、图库选照片、…

【软考】设计模式之状态模式

目录 1. 说明2. 应用场景3. 结构图4. 构成5. 优缺点5.1 优点5.2 缺点 6. java示例6.1 非状态模式6.1.1 问题分析6.1.2 接口类6.1.2 实现类6.1.3 客户端6.1.4 结果截图 6.2 状态模式6.2.1 抽象状态类6.2.2 状态类6.2.3 上下文类6.2.4 上下文类 1. 说明 1.允许一个对象在其内部状…

ArcGIS矢量裁剪矢量

一、利用相交工具 Arctoolbox工具一分析工具一叠加分析一相交

react native

简介 React Native 就是使用React和应用平台的原生功能来构建 Android 和 iOS 应用的开源框架。在 Android 和 iOS 开发中&#xff0c;一个视图是 UI 的基本组成部分&#xff0c;React 组件通过 JavaScript 来调用这些视图。可以构建自己的 Native Components(原生组件)&#…

C# wpf 嵌入hwnd窗口

WPF Hwnd窗口互操作系列 第一章 嵌入Hwnd窗口&#xff08;本章&#xff09; 第二章 嵌入WinForm控件 第三章 嵌入WPF控件 文章目录 WPF Hwnd窗口互操作系列前言一、如何实现1、继承HwndHost2、实现抽象方法3、xaml中使用HwndHost控件 二、具体实现1、Win32窗口2、HwndSource窗…

思腾合力出席文化和旅游虚拟现实应用推广交流活动并作主题演讲

3月21日&#xff0c;由文化和旅游部产业发展司主办&#xff0c;中国信息通信研究院、北京市石景山区文化和旅游局、中国动漫集团有限公司承办的“数字赋能文旅场景建设行动——文化和旅游虚拟现实应用推广交流活动”在北京首钢一高炉SoReal科幻乐园成功举办。 思腾合力CMO徐莉受…

【第028篇】用IDEA打开并运行Eclipse创建的项目

下图我使用的是2021版本的idea 一、 导入 首先&#xff0c;点击左上方【File】-【New】-【Project from Existing Sources】 在目录中选择自己要导入的eclipse动态项目&#xff1b; 3、这里选择【import project from external model】&#xff0c;再选择【eclipse】&#…

【jenkins+cmake+svn管理c++项目】Windows环境安装以及工具配置

一、目标和环境 目标&#xff1a;搭建一个jenkins环境&#xff0c;实现jenkins调用cmake和svn和VS编译c项目&#xff0c;并将生成的库上传svn。 环境&#xff1a;win10虚拟机&#xff08;练习流程用&#xff0c;正式用的话还是放到服务器&#xff09;&#xff0c;VS2017. 二、…

Flask python :logging日志功能使用

logging日志的使用 一、了解flask日志1.1、Loggers记录器1.2、Handlers 处理器1.3、Formatters 格式化器 二、使用日志2.1、官网上的一个简单的示例2.2、基本配置2.3、具体使用示例2.4、运行 三、写在最后 一、了解flask日志 日志是一种非常重要的工具&#xff0c;可以帮助开发…

pandas 函数

pandas是基于numpy数组构建的&#xff0c;但二者最大的不同是pandas是专门为处理表格和混杂数据设计的&#xff0c;比较契合统计分析中的表结构&#xff0c;而numpy更适合处理统一的数值数组数据。pandas数组结构有一维Series和二维DataFrame。 Series的字符串表现形式为&#…

java Web线上网游商品交易平台用eclipse定制开发mysql数据库BS模式java编程jdbc

一、源码特点 jsp线上网游商品交易平台是一套完善的web设计系统&#xff0c;对理解JSP java SERLVET mvc编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,eclipse开发&#xff0c;数据库为Mysql5.0…

基于springboot的交通管理在线服务系统的开发

传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装交通管理在线服务系统软件来发挥其高效地信息处理的作用&#xff0…

【数据结构】常见线性结构

1.线性表 线性表 &#xff08; linear list &#xff09; 是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使 用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构&#xff0c;也就说是连续的一…