本文只是UWA直播的记录,感兴趣的小伙伴可以去看视频,本文只是为了加深记忆。
https://blog.uwa4d.com/archives/1875.html
元素更新:
相同点:填充ui顶点数组
- 无论ugui还是ngui都有对应的类存储ui的顶点属性,这个顶点类会跟每个ui的顶点元素对应绑定。会有几个数组去存当前ui的UI属性,当ui发生变化是要通过对应的类,去填充对应的数组,即当顶点数越多,需要更新的点就变多,填充数组的过程也就越长。ngui:UIGeometry;ugui:VertexHelper;
- 对于"动态"的元素,尽量少用outline,和Tiled Sprite
- outline:会把四边形重复5遍,导致顶点数*5,也会导致顶点数比较多。更新比较慢
- Tiled:image type,会自动复制出很多三角形和顶点
- “动态”长文本,运行时修改文字,哪怕没有outline一个text中文字过多(文本优化)。
- 尽量减少这些对象(1,2中提到的)的Canvas的重建,每次重建也会从新填充所有顶点数据。
- 对于"动态"的元素,尽量少用outline,和Tiled Sprite
不同点:更新方式
- NGUI:UIPanel.LateUpdate是NGUI刷新的主逻辑,负责UI更新的操作,每帧都会执行,并且每帧都会有UIPanel.UpdateWidgets的调用(更新每一个激活状态Widget的位置,大小等,都会有一个更新和获取的过程)。如果在更新的过程中发现widget发生了变化,就进行一些列的操作。即使widget没有变,那么也会产生对应的轮询。所以说在NGUI中有大量的元素在里面,哪怕是完全静止的也会有性能开销。
- UGUI:Canvas.SendWillRenderCanvas是UGUI刷新UI的方法。由两个队列进行:m_LayoutRebuildQueue和m_GraphicRebuildQueue;这两个队列会记录layout相关以及Graphic相关的元素的变化。在渲染之前会在SendWillRenderCanvas回调中处理这两个队列。也就是说在ui没有变化的时候消耗是很小的。
应用场景
- 动态的HUD缓存机制的影响:在使用HUD时,考虑到性能,一般会缓存一部分对象,把不用的不用的对象隐藏起来,“隐藏”的方法有很多,不同的UI下不同的方案,对性能也会产生影响。
- NGUI:
- 适量元素:Color.a = 0, 移出。Scale = 0的话仅仅是网格变成0,但是顶点数还在。drawcall也会提交。
- 大量元素:setActive(false),上面提到,激活状态widget也会消耗轮询的时间,所以大量的元素最好就是SetActive=false
- Timer + 2级缓存:
- UGUI:
- Scale = 0 (会把顶点移出)或者 Alpha Group = 0,(CanvasGroup.alpha =0)或者禁用Canvas组件:这三种方式都不会有顶点的重建,不会触发ui的更新。但是会减少面数和重绘。还不会触发setActive的回调。
- 不要使用color.a = 0,因为在这种变化对于面片数没有任何变化,也就不能降低drawcall,对overdraw也没有任何效果。
Draw Call的合并规则
渲染顺序
NGUI:widget的depth,以UIPanel为单位,根据depth的大小,去做排序,把相同材质的进行合并。
UGUI:hierarchy(黑盒:比较难分析出为什么drawcall没有合并)
- 重叠检测:当两个ui(比如按钮),重叠的时候,批处理就取消了!!
- 分层合并,在UGUI中有“层”的概念,当“层”一样,且图集一样是,会进行合批处理,但是当有一个ui多出一层时,合批就会取消!!!
调试工具
NGUI:DrawCall Tool
UGUI:Frame Debugger
影响:
- UGUI不好处理的元素:
- 不规则的图标,可能导致ui的重叠。
- UI元素的旋转,当旋转之后判断重叠会是一个很大的矩形。一旦ui重叠,就会限制drawcall的合并(旋转后反而batchs减少了,什么鬼)
- 动态遮挡,
- 3D UI 一旦ui旋转,就容易发生重叠,导致drawcall上升,因为在计算重叠的时候,是把3dUI投影到2d上后计算的,旋转后投影面会变大。导致合并失败。
NGUI不好处理的元素:
- 就是要有些手动调整
网格更新机制
NGUI:UIPanel.LateUpdate两种更新方式
- UIPanel.FillDrawCall 更新单个DrawCall
- UIPanel.FillAllDrawCall更新所有DrawCall,这个函数一旦出现,如果UIPanel比较复杂,更新的开销就很高,这是容易出现峰值的地方。
UGUI:Canvas.BuildBatch更新所有UI,5.2之后ui的合并放到了子线程中,一旦子线程ui的网格开销比较高,就会在主线程中看到1,2两个函数。
- WaitingForJob
- PutGeometryJobFence
- BatchRenderer.Flush:打开多线程渲染后1,2消失,会出现BatchRenderer.Flush
建议:当优化UGUI的时候可以关闭多线程渲染,然后观察1和2,当1和2消失后,就是一个比较好的状体了。
对界面的影响
UGUI
拆分Canvas很重要原则:动静分离,修改ui会导致整个canvas刷新。
NGUI
控制FillAllDrawCalls
拆分UIPanel
比较
- 功能界面的DrawCall控制:NGUI>UGUI
- 功能界面的网格更新:NGUI>UGUI
- 动态HUD界面的网格更新控制NGUI<<UGUI
- 堆内存的优化NGUI<<UGUI
优化部分下一次写吧...