Unity UI 优化Batch方法

预备知识

什么是Draw Call,Batch?

CPU和GPU之间的通信是通过命令缓冲区来进行的,命令缓冲区中的命令有很多种类,而DrawCall是其中一种。

每次绘制一个物体在屏幕上,我们需要生成一个绘制指令给图形API。这个过程称为"Draw Call",例如下图中的“渲染模型A”命令。

图片引用自《Unity Shader入门精要》
其他种类的命令还包括改变渲染状态的命令,例如在实际发送绘制指令之前,我们需要设置好所有必须的GPU状态,例如:Mesh数据(顶点位置、顶点法线等顶点数据)、着色器代码、纹理数据、混合设置以及其他的着色器属性。

一些设置状态、改变状态的指令再加上一或多个绘制指令构成了我们所说的一次Batch。

什么是Batching?

一次Batch占用最多时间的是设置状态、改变状态的部分,相对而言,绘制指令所花的时间很短。这是为什么Unity尝试在一次Batch中将不同的渲染物体合并在一起使用相同的GPU状态进行渲染。这个过程称之为Batching。

什么是Canvas的rebatch?

Canvas组件负责组织它的组成元素进行batch,并生成对应的渲染指令然后发送给Unity的图形系统。这个过程称之为rebatch或者一次batch build。

Unity UI 优化Batch方法

正确使用Sprite Atlases

如果我们将一个Canvas上出现的所有UI元素都放在一张贴图里(使用Sprite Atlas,见References),那么当所有UI元素的材质(material)都相同时,这些UI元素将在一次Batch中全部绘制,这将极大地减少Batch总量。在这里插入图片描述
仅当同时出现在屏幕中的UI元素位于同一张贴图里的时候,才能有效减少Batch量。因为如果面板A和面板B不可能同时出现,那么将面板A和面板B的UI元素打包到同一张贴图上将不会带来Batch量的减少,因为Batch量都将是1。

调整子节点的顺序

Unity的Batch过程将从上至下遍历元素层级结构,并不断地收集使用相同材质、相同纹理并且没有“中间层”的元素。
“中间层”指的是一个与目标元素有着不同的材质,且其包围盒(Bounding Box)与两个本可以进行Batch的元素发生了重叠,并且层次关系上位于两个本可以进行Batch的元素中间。

当有中间层的存在时,会让本可以合并在一个Batch中的元素被打断。

这个问题常常出现在text和sprite彼此接近:有时候文字的包围盒(Bouding Box)可能会不经意间与相邻的sprite重叠而没有被发现,因为大部分文字的多边形是透明的。

通常有两种方式解决:

  1. 将相同材质和纹理的元素在层级上放在一块,而不要穿插中间层元素在期间。
  2. 仔细调整元素的位置,减少不经意的重叠。

注意:Unity中的选择框并不代表着包围盒,例如下列例子中文本并不会成为中间层。
在这里插入图片描述
包围盒一般是刚好能放下图片的矩形。

下列例子出现了打断Batch的现象:
在这里插入图片描述
在这里插入图片描述

分割画布(Canvas)

分割画布的策略

因为每当一个Canvas的任何组成元素的一个可绘制组件发生改变时,这个Canvas就需要rebatch,所以我们通常可以将重要的Canvas划分成至少两部分:

  1. 在一个Canvas中,放置所有静止的、不变的元素,比如背景图和文本。这样的话,该Canvas只需要batch一次。
  2. 在第二个Canvas中,放置所有动态改变的元素。当动态改变的元素增长的足够大的时候,就可能需要进一步地对其进行划分:划分成改变频繁的、改变不频繁的多个Canvas。同时,如果我们让同时改变的元素位于同一个Canvas将带来好处,这样它们将不会分别触发batch,导致额外的开销,例如进度条图片和进度条文本,它们常常依赖于相同的底层数据(进度加载值),并且同时改变。

分割画布的方式

分割画布有两种方式:

  1. 将元素移动至Sub-canvas
  2. 将元素移动至Sibling Canvas

Sub-Canvas是指嵌套在Canvas下的子Canvas。

Sibling Canvas是指独立的一个新的Canvas,与原先的Canvas保持同级。

当部分UI有自己的绘制深度控制时,例如一直在其他层的上方或者下方时(比如新手引导的箭头),我们常常分割这些元素到Sibling Canvas中。

大部分情况下,Sub-Canvas是比较好的分割方式,因为它们继承了父Canvas的显示设置。

分割画布分割的越多越好吗?

分割画布分割得越多,那么因为个别可绘制元素的改变导致rebatch时,rebatch影响到的元素越少,其速度越快。但是Canvas系统并不会在分割的Canvas之间合并batch,两个不同的Canvas至少产生两次Batch,所以并不是分割得越多越好。

References

  1. 浅谈Draw Call和Batch的区别
  2. How to see why your draw calls are not batched in 5.6
  3. Unity Learn Tutorial :Optimizing-Unity-UI
  4. Sprite Atlas
  5. 《Unity Shader入门精要》2.4.3小节
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值