前言
目前国内手游的开发过程中,大部分业务玩法都是围绕着UI进行的。一个玩法业务不管是大型还是小型,UI上能占用40%-60%的工作量,不过当然也与玩法类型也有关系,玩法越偏3D,UI占有率越低,玩法越偏2D,UI占有率就越高,甚至能达到100%。博主作为一个3年多工作经验的U3D小白,日常工作大部分都跟UI息息相关,积累了不少的工作经验。趁现在空闲时间比较多,整理一下对UI框架的理解。
一个好用的UI框架在博主看来起码要能支持到这几种功能:
- 支持UI的Init,Enable,Show,Disable,Destroy,Visible, Update这些基本事件回调的编写,我们的日常工作大多也是基于这些回调进行功能上的开发。
- 支持多个不同的层次栈,多个栈可以处理不同层级需求。新界面一定处理层次栈节点的末尾。
- 支持多个不同的显示栈,每个显示栈只能有一个UI进行显示。控制打开新界面时,是否隐藏当前显示的界面。关闭新界面时,恢复对隐藏界面的显示。
- 尽量代码逻辑处理要做到同步,不要让业务人员去思考异步代码的编写,因为这还涉及异步资源的释放,会导致日常开发的困难。
- UI自己申请的资源要自己做到释放,比如在Enable有自动注册一些功能,例如事件监听,需要在Disable去主动的解绑,避免业务人员在开发过程还要大量思考内存泄露问题。
- 需要有定时销毁UI的功能,避免一些关闭的UI长时间占据内存。
- 支持界面UI嵌套逻辑,我们日常业务开发过程中,常常会碰到如下逻辑,一个主界面有2个页签,点击任意页签会显示不同的UI。我认为比较好的UI逻辑是,主界面为UI_A,嵌套2个子UI(UI_B,UI_C),点击左页签,会显示UI_B,隐藏UI_C;点击右页签,会显示UI_C,隐藏UI_B。
- 支持自定义参数传递,需要从父UI传递到子UI。在开发成就相关的功能时,常常需要我们跳转到相关的界面,并且还要在对应的界面进行一些展示处理。
- 同时打开多个UI时,要根据调用打开的接口的顺序按序显示UI,而非通过资源加载完成后的顺序去显示。
- UI框架要维护好已打开界面的缓存和释放,避免界面频繁重新加载,以及不能释放导致的内存泄露问题。
题外话,顺便说一下目前项目框架采用一些的设置:
- 采用UGUI框架。
- Root节点上Canvas,采用Screen Space - Camera的Render Mode,Root底下的层次栈节点不能选择Override Sorting,依赖本身的层次处理层级关系。
- UI上不含有Canvas,所有UI默认为单例,不允许生成多个相同的UI界面。
UI配置
在开发UI时,有一些关键配置我们可以单独配置预制体上,方便我们进行开发调整,比如:
- UI名称
- 所处栈名称
- 打开后是否显示黑底
UI接口
接下来列举一些工作常用的UI接口,以及对这些接口起码达到的期望。
ShowUI
函数:ShowUI(string key, Param param = null)
参数:
- key:UI名称
- param:对应UI界面的传入参数
功能:
- key不区分该UI是子UI还是父UI,假如子UI,自动去寻找父UI,并实际上调用父UI的打开接口。
- param需要自动实例化父UI的param(可以通过反射的方式实例化),并在父param中存储当前需要打开的子UI对象名称,方便父UI做Show逻辑时知道当前要显示哪个子UI界面。
- 如果UI界面资源未加载,进行加载,加载完成进行父UI、子UI的初始化;
- 根据打开UI时设置的showPriority,将该UI节点设置到层次栈的末尾,保证在同层次栈内该UI一定能显示出来。隐藏跟该UI同显示栈的其他节点(Visibele)。
CloseUI
函数:CloseUI(string key)
参数:
- key:UI名称
功能: - 隐藏该UI节点,并显示出跟该UI同显示栈的下一个UI节点。