1.UGUI结构
1.渲染
UGUI渲染都是由三部分组成的,layout,material和mesh,mesh的操作成为Rebatch,mat和layout的操作成为Rebuild,大部分UI的消耗都这两个地方。
CanvaUpdateRegistry 驱动整个注册组件,通知要渲染的组件。
Graphic 大部分控件的基类,他组织mesh和mat,并且把他们传递到CanvasRender类。
CanvasRender类用来负责底层渲染,链接Canvas和渲染组件,他不负责渲染,Canvas把他传过来的数据进行组织合批等;
Canvas对几点下的Graphic进行合批,Graphic设置了某个是要dirty了,就会重建canvas。
Batch构建过程(Canvas)
- Batch , 构建过程是指Canvas通过结合网格绘制它所承载的UI元素,生成适当的渲染命令发送给Unity图形流水线。Batch的结果被缓存复用,直到这个Canvas被标为dirty,当Canvas中某一个构成的网格改变的时候就会标记为dirty。
- Canvas的网格从那些Canvas下的CnavasRenderer组件中获取,但不包含任何子Canvas。
- 计算Batch要求按照深度排序网格,测试它们是否有重叠,共享材质等等。这个过程是多线程的,在不同的CPU架构下性能表现非常不同,特别是在手机芯片(通常CPU核心很少)和现代桌面CPU(通常拥有四核心或者更多)之间非常不同。
Rebuild过程(Graphics)
- Rebuild , 过程是指Layout和UGUI的C#的Graphic组件的网格被重新计算,这是在CanvasUpdateRegistry类中执行的。这是一个C#类,它的源码可以在Unity的Bitbucket上找到。
CanvasUpdateRegistry , 类中,PerformUpdate方法,当一个Canvas组件触发它的WillRenderCanvases事件时,这个方法就会被执行。这个事件每帧调用一次。
PerformUpdate , 函数运行的三个步骤:
1- 通过ICanvasElement.Rebuild函数,请求rebuild被Dirty的Layout组件。
2- 所有被注册的裁剪组件(例如Mask),对需要被裁剪的组件进行剔除。这在ClippingRegistry.Cull中执行。
3- dirty的Graphic组件被要求rebuild其图形元素。 - Layout 和 Graphic 的 rebuild ,
Layout:Layout rebuild , 三个部分 PreLayout , Layout , PostLayout
Graphic:Graphic rebuild ,两个部分 PreRender , LatePreRender
- Layout Rebuild , 要重新计算一个或者多个Layout组件所包含的UI组件的适当位置(以及可能的大小),有必要对Layout应用层次的排序。在GameObject的hierarchy中靠近root的Layout可能会影响改变嵌套在它里面的其他Layout的位置和大小,所以必须首先计算。 为此,UGUI根据层次结构中的深度对dirty的Layout组件列表进行排序。层次结构中较高的Layout(即拥有较少的父transform)将被移到列表的前面。然后,排序好的Layout组件的列表将被rebuild,在这个步骤Layout组件控制的UI元素的位置和大小将被实际改变。关于独立的UI元素如何受Layout组件影响的详细细节,请参阅Unity Manual的UI Auto Layout章节。 [ 这就是为什么unity的布局组件一旦形成嵌套,套内组件将失效的原因 , unity也暂时未开放布局执行层级顺序的接口 , 仅在UGUI代码中可见但不未公开 ]
- GraphicRebuild , 当Graphic组件被rebuild的时候,UGUI将控制传递给ICanvasElement接口的Rebuild方法。Graphic执行了这一步,并在rebuild过程中的PreRender阶段运行了两个不同的rebuild步骤:1.如果顶点数据已经被标为Dirty(例如组件的RectTransform已经改变大小),则重建网格。2.如果材质数据已经被标为Dirty(例如组件的material或者texture已经被改变),则关联的Canvas Renderer的材质将被更新。Graphic的Rebuild不会按照Graphic组件的特殊顺序进行,也不会进行任何的排序操作。
2.事件
StandaloneInputModule处理不同的输入操作,调用ExecuteEvents触发对应事件。
Graphic在OnEnable时候注册到GraphicRegistry,进行相关查询。RaycasterManager可以查询