unity UI性能的四类问题
- Canvas Re-batch 时间过长
- Canvas Over-diry,Re-batch次数过多
- 渲染网格顶多时间过长
- Fill-rate Overutilization (UI shader中片源着色器利用率过高)
Canvas负责管理UGUI元素,负责UI渲染网格的生成与更新,并向GPU发送DC指令。
canvas绘制之前都需要一个合批的过程,如果canvas下的UI每帧保持不变,那么只需要合批一次,并且保存记录,下一帧还用这个结果。如果UI发生了变化,这是canvas需要重新匹配几何体,而这个canvas就会被diryt(脏标记),这是被标记的diryt的canvas就会触发Re-bacth。重新需要合批。
Canvas Re-batch过程
- 根据UI深度关系进行排序
- 检查UI元素的覆盖关系
- 检查UI元素材质并进行合批
合批是多线程进行的。所有和每个平台的硬件设备有一定关系。
UGUI渲染细节
- UGUI中渲染是在Transparent半透明渲染队列中完成的,半透明队列的绘制顺序是从后往前画,由于UI元素做Alpha Blend,我们在做UI时很难保障每一个像素不被重画,UI的Overdraw太高,这会造成片元着色器利用率过高,造成GPU负担
- UI SpriteAtlas图集利用率不高的情况下,大量的完全透明的像素被采样也会导致像素被重绘,再次造成片元着色器利用率过高。同时纹理采样器浪费了大量的采样在无效的像素上,导致需要采样的图集像素不能尽快的被采样,造成纹理采样器的填充率过低,同样会带来性能问题
UGUI性能优化
使用canvas的使用准则
- 将所有可能打断合批的层移动到最下边图层,尽量避免UI元素出现重叠区域
- 可以拆分使用多个同级或嵌套的Canvas来减少Canvas的ReBatch复杂度
- 拆分动态和静态的对象放到不同的canvas下,减少ReBatch次数,降低DC
- 不使用Layout组件(如果UI布局是不规则的话 就不用layeout这样能减少rebuild 提升Re-batch的渲染效率)
- Canvas的RenderMode尽量Overlay模式,减少Camer调用的开销
UGUI摄像(Raycaster)优化
- 必要的需要交互的UI组才开启Raycast Target
- 开启Raycast Targets的UI组件越少 层级越浅 性能越好
- 对于复杂的控件,尽量在根节点开启 Raycast target
UI字体
- 每个字体都是单独的四边形。避免字体快重叠,造成合批打断
- 字体网格重建的情况有一些几点
- UItext组件发生变化
- 父级对象发生变化
- UI组件或父对象enable/disable时
所以再大量文字的UI上Re-batch的时候会发生掉帧
UGUI 最容易产生性能问题的组件 滚动视图 Scroll view
- 使用RectMask2d组件裁剪
- 使用基于位置的对象池作为实例化缓存