找回密码
 立即注册
查看: 296|回复: 0

[笔记] UGUI源码解析(二十七)总结篇

[复制链接]
发表于 2022-1-4 10:14 | 显示全部楼层 |阅读模式
1、渲染细节

当使用Unity UI 制作用户界面时,记住,所有的被Canvas绘制的图形都是被放在透明渲染队列。这意味着,Unity UI产生的图形都会使用透明混合(alpha blending)从后向前渲染。有一个重要的性能点要注意:图形上的每一个像素都会被采样,即使它被另一个不透明的图形完全覆盖。在移动设备上,大量的的过度绘制(overdraw)可以快速超出GPU填充率的上限。

2、合批过程(Canvases)

合批过程是指Canvas合并UI元素的网格,并且生成发送给Unity渲染管线的命令。Canvas使用的网格都是从绑定在Canvas上的CanvasRenderer获得,但是不包含子Canvas的网格。UGUI的层叠顺序是按照Hierarchy中的顺序从上往下进行的,也就是越靠上的组件,就会被绘制在越底部。所有相邻层的可Batch的UI元素(具有相同材质和纹理),就会在一个DrawCall中完成。

UGUI合批策略

  • 父节点Z != 0,则下面的元素都无法合批了。子UI元素Z值不为0时,会被视为3D UI,不参与合批。
  • 设置Canvas.overrideSorting为true
  • 设置Canvas.sortingOrder为窗口在Hierarchy下的排列顺序
  • 设置Canvas.sortingLayerID为0
  • 设置Canvas.sortingLayerName为SortingLayer.IDToName(0)
  • 根据功能适用性,合理使用Atlas图集。
  • 慎用Mask组件

3、重绘过程(Graphics)

重绘过程是指Unity UI 的 图形组件的排版和网格被重新计算。这在 CanvasUpdateRegistry类中执行。当Canvas组件触发WillRenderCanvases事件时都会调用这个方法。这个事件每一帧都会执行一次。在CanvasUpdateRegistry内部,需要关注的方法是PerformUpdate。

PerformUpdate执行三个步骤:

  • 标记为dirty的排版组件通过ICanvasElement.Rebuild方法重建布局,排版重建分成三个过程(PreLayout, Layout 和 PostLayout)。
  • 任何注册过的裁剪组件(如mask),需要去裁剪所有可剔除的组件。这是通过ClippingRegistry.Cull实现的。
  • 被标记为dirty的图形组件,通过ICanvasElement.Rebuild方法重建它们的图形元素,图形重建包含两个过程(PreRender 和 LatePreRender)。

布局重建:
自动布局系统按以下顺序评估和执行布局:

  • 通过调用ILayoutElement组件上的CalculateLayoutInputHorizontal来计算布局元素的最小值,首选值和灵活宽度。这是以自下而上的顺序进行的,孩子在父母面前计算,这样父母可以在他们自己的计算中考虑到孩子的信息。
  • 通过调用ILayoutController组件上的SetLayoutHorizontal,根据父对象的可用宽度,来计算和设置子对象布局元素的宽度。这是按照自上而下的顺序执行的,因为孩子的父母分配的子宽度需要根据父母的可用宽度进行分配。在这一步之后,布局元素的Rect变换具有新的宽度。
  • 通过调用ILayoutElement组件的CalculateLayoutInputVertical来计算布局元素的最小值,首选值和灵活高度。这是以自下而上的顺序进行的,孩子在父母面前计算,这样父母可以在他们自己的计算中考虑到孩子的信息。
  • 通过调用ILayoutController组件的SetLayoutVertical,根据父对象的可用高度,来计算和设置子对象布局元素的高度。这是按照自上而下的顺序执行的,因为子女的高度需要根据父母的可用高度计算,子女是在父母之后计算的。在这一步之后,布局元素的Rect变换有了新的高度。

何时触发布局重建:

  • 更改LayoutElement布局元素的属性时,比如修改Min Width,Preferred Width等属性。
  • 在OnEnable和OnDisable中
  • OnRectTransformDimensionsChange(RectTransform大小发生改变时)
  • OnValidate (只能编辑器中,非运行状态)
  • OnDidApplyAnimationProperties(应用动画属性时)

图形重建:
Rebuild方法
在Canvas渲染前被调用,在这个方法里会调用UpdateGeometry和UpdateMaterial更新顶点和材质。
UpdateGeometry方法
调用DoMeshGeneration方法,如果rectTransform不为空,且宽高都大于0,调用OnPopulateMesh,实际上只是把顶点和三角形信息保存到了s_VertexHelper里。然后获取所有的IMeshModifier类型的组件,(IMeshModifier是一个接口,需要依据顶点信息的组件继承自它,例如Shadow就间接继承自它),调用IMeshModifier的ModifyMesh方法,修改Mesh信息。最后将s_VertexHelper里修改后的信息设置给canvasRenderer。概括的说就是,把顶点和三角形信息进行修改,并设置给CanvasRenderer。
UpdateMaterial方法
更新canvasRenderer的材质和纹理。在给canvasRenderer设置材质时,会遍历所有IMaterialModifier类型的组件,调用IMaterialModifier.GetModifiedMaterial方法,用于重建图像时,获取修改后的Material,来实现遮罩效果。

推荐大神写的一篇自定义绘制的博文:
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-5-12 03:13 , Processed in 0.123301 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表