UGUI原理学习笔记

本文详细介绍了Unity的UGUI系统,包括合批原理、网格重建因素及其对性能的影响。强调了优化策略,如减少网格重建频率、合批策略优化、屏幕填充率优化和字体优化等,旨在提升UI系统的效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

重要概念

  • Canvas Batch:Canvas下的UI元素最终都会被Batch到同一个Mesh中,而在Batch前,会根据这些UI元素的材质(通常就是Atlas)以及渲染顺序进行重排,在不改变渲染结果的前提下,尽可能将相同材质的UI元素合并在同一个SubMesh中,从而把DrawCall降到最低。Batch的结果会被缓存复用,知道这个Canvas被标记为dirty.
  • Unity官方的重要提示:当给定Canvas上的任何可绘制UI元素发生更改时,Canvas必须重新执行合批过程。此过程重新分析Canvas上的每个可绘制UI元素,不管它是否被修改。注意:更改是指影响UI元素外观的任何变动,包括修改sprite、transform的Position 和Scale、文本网格的text等等。
  • Canvas嵌套:Canvas可以嵌套使用,一个子Canvas下dirty的子物体不会触发父Canvas的rebuild

网格重建因素

UI顶点属性变化会引发网格更新

  • 修改Image、Text的Color属性会改变顶点的颜色UIVertex.color
  • 修改RectTransform的Size、Anchor、Pivot等,会改变顶点的位置UIVertex.position
  • 注意:在UGUI中颜色的变化是通过修改顶点色实现的,避免生成了新的DrawCall
  • 注意:UIVertex.position记录的是本地空间下的坐标
    网格重建流程图:
    在这里插入图片描述
    流程图说明:
  • 该过程由CanvasUpdateRegistry监听Canvas的WillRenderCanvases上图中的1而执行,主要是对当前标记为dirty的layout和graphic执行rebuild
  • 在rebuild layout前会对Layout rebuild queue中的元素依据他们在hierarchy中的层次进行排序(上图2),排序的结果是越靠近根节点越会被优先处理。
  • rebuild layout (上图3)主要是执行ILayoutElement和ILayoutController接口中的方法来计算位置,rect的大小等布局信息。
  • rebuild graphic(上图4)主要是调用UpdateGeometry重建网格的顶点数据(上图5)以及调用UpdateMaterial更新CanvasRender的材质信息(上图6)

合批原理

UGUI的合批规则是进行重叠检测,然后分层合并。
  • 第一步计算每个UI元素的层级号:如果由一个UI元素,它所占的矩形范围内,如果没有任何UI在它的底下那么它的层级号就是0(最底下);如果有一个UI在其底下且该UI可以和它batch,那么它的层级号与它底下的UI层级号一样;如果有一个UI在其底下但是却无法与它batch,那么它的层级号为它底下UI的层级+1;如果有多个UI都在其下面,那么按前两种方式遍历计算所有层级号,其中最大的那个作为自己的层级号。
  • 第二步合并相同层级中可以batch的元素作为一个批次,并对批次进行排序:有了层级号之后,unity会将每一次嗯的所有元素进行一排序(按照材质、纹理等信息),合并掉可以batch的元素成为一个批次。经过以上排序,就可以得到一个有序的批次序列了。这个时候Unity会再做一个优化,即如果相邻间的两个批次正好可以batch的话就会进行Batch。合批的batch数据,最后会分别放在CanvasMesh的SubMesh里

UGUI开发过程中常见问题

  • 过多的GPU片段着色器使用率(如屏幕填充率过高)
  • 过多的CPU时间开销再重建一个画布上
  • 过多的CPU时间开销再生成顶点上(通常是文本)
  • 过多的画布重建次数

优化策略

  • 网格重建优化策略
  • 屏幕填充率优化策略
  • 合批优化策略
  • 字体优化策略
  • 滚动视图优化策略
  • 其他优化策略

网格重建优化策略

  • 使用尽可能少的UI元素:在制作UI时,一定要仔细检查UI层级,删除不必要的UI元素,这样可以减少深度排序的时间以及Rebuild的时间。
  • 减少Rebuild的频率:将动态UI元素(频繁改变例如顶点、alpha、坐标、和大小等元素)与静态UI元素分离出来,放在特定的Canvas中。
  • 谨慎使用UI元素的SetActive操作:因为他们会触发耗时较高的rebuild
  • 谨慎使用Canvas的Pixel Perfect选项
  • 谨慎使用Tiled类型的Image

屏幕填充率优化策略(OverDraw)

  • 禁用不可见面板:比如当打开一个系统时如果完全挡住了另外一个系统,则可以将被遮挡住的系统面板禁用。(可以通过又该Canvas的Layer隐藏面板)
  • 不要使用空的Image做按键响应:可以实现一个只在逻辑上相应Raycast但是不参与绘制的组件
using UnityEngine;
using UnityEngine.UI;

public class Empty4Raycast : MaskableGraphic
{
    protected Empty4Raycast()
    {
        useLegacyMeshGeneration = false;
    }

    protected override void OnPopulateMesh(VertexHelper toFill)
    {
        toFill.Clear();
    }
}

将以上组件添加至没有Image的Obj上即可

  • Polygon Mode Sprites:如果图片边缘有大片留白就会产生很多无用填充。Unity和TexturePacker目前都支持PolygonMode。也就是说将原来的举行Sprite用更加紧致的Polygon来描述。

合批策略优化(DrawCall)

  • 相同层级原则:父节点下所有子节点,精良保持相同的层次结构。相同层级下的UI元素可以Batch.
  • Mask组件:mask组件使用的模板缓存,mask中的UI元素无法与外界UI元素合批,Mash组件还会额外增加2个DrawCall
  • 影藏的Image:Image组件中的sprite为空,都是占用DrawCalll渲染的,并且还会打断前后元素的合批。
  • Screen Space-Camera模式:一个Canvas中的任何一个元素只要在屏幕中,则这个Canvas中的其他元素鸡是再屏幕外DrawCall任然不会减少 也就是说仍然会绘制。
  • Hierarchy穿插重叠问题:不同图集图片尽量不要重合覆盖 会打乱合批。

字体优化策略

  • Text的网格重建:Text组件被重新启用的时候,会重建Text的网格。如果含有大量文字,会造成严重的CPU开销。
  • 提前生成动态字体
  • 使用美术数字:游戏的分数减血等可以使用美术数字(精灵图片)来代替Text组件。
  • 谨慎使用Text的Best Fit选项
  • 减少长文本Tex的变动,慎用UI/Effect:描边和阴影效果都会增大斯贝德定点数。

其它优化策略

  • 禁用无用的Raycast:UGUI的touch处理消耗也可能成为性能热点。因为UGUI在默认情况下会对所有可见的Graphic组件调用Raycast.对于不需要接受touch时间的Graphic一定要禁用raycast
  • OverrideSorting:子Canvas中的OverrideSorting属性将会造成Graphic Raycast测试停止遍历Transform层级。
  • UI对象的坐标Z值:Z值不为零的时候会影响对象渲染顺序并不能合批
  • CanvasGroup的使用

优化工具

  • Profiler
  • FrameDebug
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值