Unity UI框架设计

之前的工作中有比较多UI相关的内容(毕竟作为一个菜鸟,来到一个很多经验丰富老鸟的团队,被分配去整UI还是挺正常)。
那么既然做了比较多这部分的工作,就花了点时间整理以下游戏中UI模块的设计思路(这里主要还是针对UI界面比较复杂的项目),整理出来的工程链接是
https://download.csdn.net/download/qq_31480839/12514298
我做这个事情的出发点是为了学习,所以并没有去copy项目中的代码,是按照自己理解写的这部分东西,并且在一些细节上也进行了精简,所以工程中的代码没有进行复杂的测试,要自行检测。
这个模块中有比较多的东西,所以有不明白的或者是建议,都可以私信交流。


p1:Unity3D UI 模块框架设计1.需求分析

1:数据和UI的分离。采用MVC架构,模块耦合度低,重用性高。
2:界面的打开流程大致定为OnUIInit, OnUIOpen, OnUIShow, OnUIHide, OnUIClose。 UI被创建的过程中会调用OnUIInit和OnUIOpen,其中OnUIInit只会被调用一次。
OnUIShow会在界面显示的时候调用,setGameobjectActive(true)时也会去调用OnUIShow,主要是针对一些界面打开时需要播放动画以及以及协程或者其它相关的内容。
OnUIHide相对于OnUIShow,是在关闭显示时调用。
3:UI界面的打开需要能够实现以下功能:
(1)能够正常打开一个界面。(2)能够在一个界面上打开另一个界面,重叠显示。(3)能够在一个界面上打开一个stack UI,打开时将之前的界面隐藏,关闭时能够将之前的界面显示出来。
(4)能够在一个界面的固定位置位置打开一个UI。(5)有一个队列UI,能够逐个打开。 (6)能够显示弹窗,弹窗在上层。
4:粒子特效的显示问题。
5:界面的重复利用,unity prefab初始化是一个比较耗时的过程,如果能够将使用过的prefab缓存,那么就能通过内存换取性能。
6:父界面和子界面之间的消息通知

p2:Unity3D UI 模块框架设计2.MVC架构

原因:MVC架构,数据和UI分离,模块耦合度低,重用性高。
操作:在需要导出的节点中添加UIItemVariable,选择你要导出的type,并输入导出的名字(没有的话就是节点名称)。点击unity目录中GameTools/ProcessUIPrefab, 拖动prefab,点击export,查看提示信息,
如果有success提示的话,那么就能在Script/UIExported/下看到相应的view文件。(具体导出的细节在ProcessUIPrefab文件中)

可以看下Test2这个prefab,导出之后的文件是Test2View.这个界面上只有一个关闭按钮,View就是给我们提供这个关闭按钮的引用的。这就是MVC中的View。

看UITest2Controller,这个就是MVC中Controller。Controller中首先需要写出指向的prefab在resources中的路径。其次需要Create对应的view。这时就能拿到view中的component进行操作.
m_View.CloseBtn.onClick.AddListener(Close);UITest2Controller取到了View的CloseBtn并注册了点击回调。

项目中的持续数据可以存储在相应的地方,如果controller需要用到数据的话可以直接访问。比如有一个AccountModel,prefab正好要显示用户名称,controller直接去AccountModel中取到数据展示出来就行。

p3:Unity3D UI 模块框架设计3.UI流程

界面的打开流程大致定为OnUIInit, OnUIOpen, OnUIShow, OnUIHide, OnUIClose。
UI被创建的过程中会调用OnUIInit和OnUIOpen,其中OnUIInit只会被调用一次。
OnUIShow会在界面显示的时候调用,setGameobjectActive(true)时也会去调用OnUIShow,主要是针对一些界面打开时需要播放动画以及以及协程或者其它相关的内容。
OnUIHide相对于OnUIShow,是在关闭显示时调用。

Controller的基类是UIBaseController,有虚函数OnUIInit, OnUIOpen, OnUIShow, OnUIHide, OnUIClose。
将一次性的处理放在OnUnInit中,每次打开需要进行的处理放在OnUIOpen中,关闭时需要进行的操作OnUIClose.
OnUIShow以及OnUIHide主要是针对界面开关时要进行的操作。
比如给按钮注册回调,可以在OnUIInit中进行注册,也可以在OnUIOpen中进行注册,但是如果是在OnUIOpen中进行注册,那么需要在OnUIClose删除回调。

p4:Unity3D UI 模块框架设计4.UI界面打开功能

UI界面的打开需要能够实现以下功能:
(1)能够正常打开一个界面。(2)能够在一个界面上打开另一个界面,重叠显示。(3)能够在一个界面上打开一个stack UI,打开时将之前的界面隐藏,关闭时能够将之前的界面显示出来。
(4)能够在一个界面的固定位置位置打开一个UI。(5)有一个队列UI,能够逐个打开。 (6)能够显示弹窗,弹窗在上层。

运行项目可以看到在运行时UIRoot下有三个节点,分别时Background,Normal,Top。这是三个层次,我们可以将UI在Background中打开,这样它是在最下面,也可以将UI加在Top中,这样就是最上层的UI。
在UIBaseScene中有OpenUI(int layer = LAYER_NORMAL), OpenStackUI(), OpenQueueUI()可以用来完成上面的界面打开功能。也可以给一个UI Add一个ChildUI.

所有打开的UI都会存在UIBaseScene,关闭时需要解除引用。存储的信息中有UIOpenMethod信息,可以处理stack打开,queue打开。

p5:Unity3D UI 模块框架设计5.粒子特效的显示问题

粒子和UI界面的穿插是一个比较麻烦的事情。我的解决思路是统一管理sortingOrder。
在ProcessUIPrefab的时候就会把Canvas particleSystemRenderer sortingGroup进行导出,component中的sortingOrder是相对值,在界面打开时,根据添加节点会有不同的baseSortingOrder.
baseSortingOrder+sortingOrder就会是最终的sortingOrder.

在UIOpen时加上BaseSortingOrder,在OnUIClose时减去BaseSortingOrder,这样是针对UI缓存,上回在normal层打开,这回在top层次打开,这样才能不出问题。

p6:Unity3D UI 模块框架设计6.界面的重复利用

缓存的基类是ResumableObject.现在只有prefab的缓存。
在UI创建的时候通过resourcemanager去查找是否有缓存的prefab,如果没有的话就会直接创建。(通过prefab路径查找)
在UIClose的时候会判断UI的缓存方式,现在只有两种,缓存或者不缓存,不缓存的话会直接删除(实例中UITest2Controller就是不缓存)。缓存的东西会被隐藏并且添加到"__PooledObjectRootTF"节点下。

p7:Unity3D UI 模块框架设计7.父界面和子界面之间的消息通知

参考Unity中sendMessageUpward,BroadcastMessage,SendMessage

上一篇:Unity3D最佳实践:避坑技巧


下一篇:搭建harbor 镜像服务器