前言
我们做系统,简单说:就是通过数据写代码去控制Prefab的显示和交互。
所以涉及到三个方面:数据,控制逻辑,显示(Prefab)。
一般的话Prefab应该是美术来做,以前我们程序也做,后来被美术吐槽了。由于这样
(我们是真的看不出来少一个像素有啥区别)和那样(难度颜色254比255很明显的暗了?),程序也懒,也不想搞这些,所以最后都是美术去做了。
数据的话因项目而异,就不说了。
主要说说控制Prefab的逻辑部分:
分四个主题去说明UI的整个流程。
第一个主题:UI的底层架构分析。
第二个主题:UI的底层架构实现。
第三个主题:UI的组件化。
第四个主题:实现一些比较特殊的系统:AVG系统、新手引导系统、来源跳转系统等等。
现在正式开始第一个主题:
UI的底层架构分析
结构底层是一个三层架构,但是却不是我们认为的MVC三层,而是View中的细分三层:UI管理层(UIManager),UI收集层(UIBaseCollect),UI层(UIBaseView)。
也就是下图中的结构
看了这个图,估计会有人有疑问,接下来我会一一讲解。
UI层
UI层就是单个UI系统:一个Prefab和一个控制脚本,脚本用于控制Prefab的显示和交互。
UI层的生命周期:加载、打开、关闭、卸载。
我们通过UI层(UIBaseView)去实现上述的四个过程
上图中UIBaseView也是每个UI(UIPanel_MessageBox、UIPanel_Loading、UIPanel_Common)的父类,这样所有的UI都会有上述的四个流程用于控制UI显示和交互。
你也许会想这样,UI的流程不就是这些么?这样UI架构不就完了么?其实远远没有你想的这个简单,往下看。
UI集合层
看下图
UIA和UIB很明显就是两个不同的UI,UIC和UID也不是不同UI,这很明显没有问题!
但是UIE和UIF呢?他们里面有相同的内容,但是却是不同的UI,那么在你制作这两个UI的过程,UIE中的内容A和UIF中的内容A你需要做两次,做两次问题也不大,但是你不知道后期还有多少个这种页面内容相识的UI,会严重的浪费人力资源,这样做多次同样的事情可不是程序员该有的思想;最关键的,如果美术说这个地方我们觉得不好看,要修改,蛋疼的人生开始了,你曾经的成果将会让你痛苦不堪,每次修改你都的去修改UIE中的内容A和UIF中的内容A;最最最怕的就是美术内容A要重新设计,你就偷着乐吧。
当成相同UI不行:因为有内容不一样的部分;当成不同UI也不行:会导致重复。这个时候我们该怎么办?
解决方案:页面拆分。
怎么拆?
将上图中UIE拆分成UIEA和UIEB,UIF拆分成UIFA和UIFD,其中UIEA和UIFA是同一个UI,
最后UIE和UIF拆分成:UIEB,UIFD,UICommon(内容A的部分)。
好了,现在就算美术要改UI我们也能减少一些工作量了。
那么我们要怎么去实现呢?
既然页面拆分了,以前打开UIE就行了,现在得打开UIEB和UICommon,并且这两个UI有相同的生命周期。
现在我们规定:每次打开的系统是一个UI集合(UIBaseCollect),UI集合里面含有不少于一个UI,并且含有一个主UI,主UI的生命周期就是UI集合的生命周期。
系统和UI集合是一个相等的概念后面就不在解释了。
以前打开一个系统就是打开一个UI,现在不是了,现在是打开一个系统就是打开一个UI集合,也就是同时打开多个UI。
以上只是页面拆分的一个好处,这里还有一个好处也很重要:如果一个UI很大并且也有隐藏的部分(达到某个条件才会显示的部分),这样的UI加载是很吃力的,关键是隐藏部分又不显示,你加载进来干吗?所以这个时候我们可以将隐藏部分拆分出去,形成单独的UI,等待合适的时机在加载进来,这样不是更加合理么?
基于以上原因,也是我们必须这样设计的理由。这样就形成了UI架构三层中的中层:UI集合层(UIBaseCollect)。
既然是中层,那么肯定拥有管理下层的能力:
UI集合层也定义了:加载、打开、关闭、卸载等必要的四个流程,目的就是用来管理UI层的UI。
UI管理层
我们知道了,每次打开一个系统会就是打开一个UI集合,同时也是打开多个UI,很棒。
为了让UI更加充满活力我们再来看一个图:
一般的UI流程:打开集合A->打开集合B->打开集合C->关闭集合C->关闭集合B->关闭集合A。
这里分两个部分来说
- 打开集合
打开集合A:直接打开
打开集合B:先关闭集合A再打开集合B(当前显示集合)
打开集合C:先关闭集合B再打开集合C(当前显示集合)
有没有发现?其实我们是先关闭当前显示的集合然后再去打开自己的集合。 - 关闭集合
关闭集合C:先关闭集合C再打开集合B(上一个集合)
关闭集合B:先关闭集合B在打开集合A(上一个集合)
有没有发现?其实我们是先关闭当前的显示集合然后打开上一个集合。
我们不可能每次打开一个UI集合都手动的关闭当前UI集合吧?
我们也不可能每次关闭一个UI集合后都手动打开上一个UI集合吧?
从两个有没有发现中我们可以规定UI集合的自动流程:
- 打开UI集合:先关闭当前显示UI集合,然后打开自己的UI集合。
- 关闭UI集合:先关闭自己的UI集合,然后打开上一个UI集合。
为了实现上述的逻辑我们设计出UI的上层:UI管理层(UIManager),管理UI集合的自动流程。
总结
通过以上的分析我们得出了UI架构的三层结构
UI管理层(UIManager):管理UI集合的自动流程,使用者只需要关注自己的UI。
UI集合层(UIBaseCollect):管理多个UI的生命周期,主UI的生命周期就是UI集合的生命周期。
UI层(UIBaseView):UI的生命周期管理,所有UI的基类。
其实并不复杂,往往简单的东西会让你觉得是真正合适的。
其实设计的最开始也是简单的,后来因为需求就变得复杂了,最后发现很多都是自己想多了,然后慢慢就变得简单了。
以上算是较为详尽的叙述了UI设计的基本结构。UI系统部分可没有这么简单,还有很多细节点会在后续一一说明。
分四个主题去说明UI的整个流程,每个主题至少一篇文章。
第一个主题:UI的底层架构分析(完)。
第二个主题:UI的底层架构实现。
第三个主题:UI的组件化。
第四个主题:实现一些比较特殊的系统:AVG系统、新手引导系统、来源跳转系统等等。
项目地址:https://github.com/xiaoyanxiansheng/SmallEyeGame
下一篇:UI层实现篇