4.2.1 UGUI系统的运行原理
UGUI是在3D网格下建立起来的UI系统,它的每个可显示的元素都是通过3D模型网格的形式构建起来的。当UI系统被实例化时,UGUI系统首先要做的就是构建网格。
也就是说,Unity3D在制作一个图元,或者一个按钮,或者一个背景时,都会先构建一个方形网格,再将图片放入网格中。可以理解为构建了一个3D模型,用一个网格绑定一个材质球,材质球里存放要显示的图片。
这里有一个问题,如果每个元素都生成一个模型且绑定一个材质球存入一张图片,那么界面上成千上万个元素就会拥有成千上万个材质球,以及成千上万张图。这样使得引擎在渲染时就需要读取成千上万张图以及成千上万个材质球,如果GPU对每个材质球和网格都进行渲染,将会导致GPU的负担重大,我们可以理解为一个材质球拥有一个drawcall会导致drawcall过高(drawcall的原理将在后面章节介绍)。
UGUI系统对这种情况进行了优化,它将一部分相同类型的图片集合起来合成一张图,然后将拥有相同图片、相同着色器的材质球指向同一个材质球,并且把分散开的模型网格合并起来,这样就生成几个大网格和几个不同图集的材质球,以及少许整张的图集,节省了很多材质球、图片、网格的渲染,UI系统的效率提升了很多,游戏在进行时也顺畅了许多。这就是我们常常在UI系统制作中提到的图集概念,它把很多张图片放置在一张图集上,使得大量的图片和材质球不需要重复绘制,只要改变模型顶点上的UV和颜色即可。
UGUI系统并不是将所有的网格和材质球都合并成一个,因为这样模型前后层级就会有问题,它只是把相同层级的元素,以及相同层级上的拥有相同材质球参数的进行合并处理。合并成一个网格,就相当于是一个静止的模型,如果移动了任何元素,或者销毁了任何元素,或者改变了任何元素的参数,原来合并的网格就不符合新的要求了,于是UGUI系统就会销毁这个网格,并重新构建一个。我们设想一下,如果每时每刻都在移动一个元素,那么UGUI系统就会不停地拆分合并网格,也就会不停地消耗CPU来使得画面保持应有的样子。这些合并和拆分的操作会消耗很多CPU,我们要尽一切可能节省CPU内存,尽量把多余的CPU让给核心逻辑。UGUI系统在制作完成后,性能优劣差距很多时候都会出现在这里,我们要想方设法合并更多的元素,减少重构网格的次数,以达到更少的性能开销目的。