UGUI的基础知识

最近在处理UGUI的效率问题,所以顺便翻译一下Unity UI的相关文档,以供查阅。

基本概念

Canvas(画布)组件是所有UI元素都需要用到的类,通过 Canvas 组件,UI元素的顶点和面得以映射到世界坐标系中,并根据 Canvas 的设置决定如何绘制。一个很神奇的地方就是,当创建一个 Canvas 元素的时候,场景里会出现一个非常硕大的平面,相对于普通的模型而言非常巨大。

image_1

图中红框里的立方体的边长是1米,旁边巨大的白色细框是 Canvas 的范围,可以看到比立方体大很多。造成这个现象的原因是UI在 Scene View 视图中绘制时,用的是1个单位对应1个像素绘制的,而在世界坐标系中,1个单位就代表了1米。

Canvas 并不是每一帧都在刷新,而是当底下的UI元素需要重新合批(rebatch)的时候才刷新,这个时候 Canvas 被认为是有修改的(dirty)。另外,顶点和面的几何信息并不是 Canvas 直接收集的,而是通过 Canvas Renderer 组件。Unity官方文档强烈建议自定义的UI组件物体上面一定要添加一个 Canvas Renderer 组件。

另外两个比较重要的基础组件包括 Graphic 组件和 Layout 组件,前者是所有UI元素的基类,提供基本的绘制接口;后者是调整UI布局的组件,只跟 RectTransforms 相关,并不依赖于 Graphic 相关的类。它们共同的特征就是在 CanvasUpdateRegistry 类中注册了监听事件,当 CanvasUpdateRegistry 收到一个 willRenderCanvases 重建(rebuild)事件的时候,会调用相应的函数处理。

UGUI渲染时有一个特性,就是所有的UI元素都是在Transparent队列中绘制的,并且不会因为被别的UI元素遮挡而剔除出渲染队列。因此,如果有全屏的UI存在的话,如果有被盖住的UI,最好是将其设为Disabled状态,或者是将Canvas组件设为Disabled,后者的效率更高一些,但是无法处理特效的显隐。

UI的合批操作

在UI重建之前,需要对Canvas组件下的UI元素进行合批,以便按照深度排序,并收集各个UI的Mesh信息。正常情况下,合批操作只会在Canvas被设为Dirty的情况下需要处理。能够导致这种情况的时间包括但不限于子元素的移动,缩放,添加,删除等操作。文档中还提到一点,收集的Mesh信息只包括Canvas底下包含的Canvas Renderer组件传回来的信息,并且不包括子Canvas。因此,如果在同一个界面中有一部分元素需要频繁修改,另一部分保持不变的情况,可以考虑给经常修改的部分单独再添加一个Canvas组件。

UI的重建过程

完成了合批操作之后,Unity会发送渲染指令给图形管道,以便完成Mesh的重建过程。如前文所述,CanvasUpdateRegistry 负责处理重建过程,关联的函数是PerformUpdate

一共有三个步骤:

  1. 被置为dirty状态的Layout组件需要通过ICanvasElement.Rebuild方法重建子UI元素的布局;
  2. ClippingRegistry.Cull方法会根据UI元素的大小裁剪掉所有注册的可裁剪元素;
  3. 被置为dirty状态的Graphic元素会重建它们的图形元素(前者Graphic指Graphic类相关的元素,后者的图形指的是实际显示的图形)

可以看出重建过程分为两部分,分别是Layout重建和Graphic重建。Layout重建有三个部分,分别是PreLayout,Layout和PostLayout。Graphic重建有两个部分,分别是PreRender和LatePreRender。

Layout重建之前,首先需要按照层级关系进行排序,考虑到更接近根物体的Layout可能会影响到层级更低的物体的Layout,因此必须先计算它们的Layout。因此,UGUI采用的是根据层级关系排序,层级越高则在Layout列表里的位置就越靠前。

ICanvasElement 组件的 Rebuild 方法被调用时,Graphic类会在PreRender这一步检查有哪些Graphic元素需要被重建。需要重建的情况包括:

  • 顶点数据被置为dirty (比如RectTransform修改了大小),则mesh信息会被重建
  • 材质数据被置为dirty (比如组件的材质球或者贴图被修改了),则同一个GameObject上挂在的Canvas Renderer的材质也会被更新

Graphic重建并不需要有任何的顺序,因此也不需要对输入进行排序。

参考文档:

https://unity3d.com/cn/learn/tutorials/topics/best-practices/fundamentals-unity-ui

Comments !

links

social