着色的Sprite实际上是在Unity的较新版本中批处理的吗?

时间:2018-07-16 10:15:58

标签: c# unity3d sprite

自从在Unity开发的第一天开始,我就看到了一些提示和内容,说我们永远不应该着色sprite。如果我们要使用不同颜色的子画面,请创建它们并将它们放置在相同的纹理中,然后交换不同颜色的子画面。

原因是着色精灵会破坏批处理。

我创建了一个小演示。


情况1

Situation 1

在6个游戏对象中使用了相同的正方形精灵。毫不奇怪。在统计中,有1批次。批量保存5个。


情况2

Situation 2

在6个游戏对象中再次使用了相同的正方形精灵,但是这次,所有这些对象都被着色为具有相同颜色值的红色。

这不是应该取消批次吗?


情况3

Situation 3

为了完整起见,我用不同的颜色给方形精灵着色。不过,我们还有1个批次和5个保存。什么都没改变。


其他信息

  1. 我在单场游戏中捕获了情况1和2,在另一场游戏中捕获了情况3。
  2. 我尝试通过更改SpriteRenderer的“颜色”字段,并在脚本中通过更改,在编辑器中直接着色精灵。结果是相同的。

2 个答案:

答案 0 :(得分:4)

SpriteRenderer组件上更改精灵的颜色不会破坏批处理。中断批处理的是在更改SpriteRenderer的sprite,材质时,甚至当您尝试使用SpriteRenderer.material属性访问材质时。

例如,

中断批处理:

SpriteRenderer sr = GetComponent<SpriteRenderer>();
sr.material.color = Color.red;

因为您正在访问材料。首次访问material属性时,它将创建新的material实例。


不会中断批处理:

SpriteRenderer sr = GetComponent<SpriteRenderer>();
sr.color = Color.red;

不会,因为它没有访问material属性。即使它不会破坏批处理,但它的一个问题是性能。这样做会影响性能。

答案 1 :(得分:3)

AFAIK,着色基本上是设置顶点颜色。这是对粒子完成的,您可以在其中设置随机的起始颜色,并且所有粒子均在一次绘制调用中呈现。顶点颜色不会更改/创建新材料。

不确定在Unity早期版本中如何处理,但子画面应为简单的四边形,因此支持顶点颜色。 Sprite着色器的着色方式可能相同。

通常来说,您是对的。更改着色器属性将创建该材质的副本,或者将更改材质本身并影响使用该材质的所有实例。您是在sprite材质还是在spriteRenderer上使用了着色?

我可以想到使用MaterialPropertyBlocks,但也许Unity确实对精灵使用了。


更多细节需要澄清:

A 您有“ Material01.mat”-绿色。您将此材质复制到10个精灵。您想有10种颜色吗?您必须创建10种材质,每种材质都具有所需的颜色-10个Draw调用。

您可以通过脚本执行相同操作,只需更改material.color。但是Unity会为您复制材料。仍然有10个抽奖电话。有些人感到困惑,为什么它会中断批处理,直到他们得知这一点。

B 您更改了RENDERER的色调。此Sprite Renderer会使用vertex color属性将着色颜色写入您的sprite顶点(可能为4?)中。它基本上是免费的,因为它们仍然会传输到gpu(afaik)

如上所述,粒子系统中使用了相同的方法,以允许具有1个抽奖的彩虹粒子。

因此,任何粒子着色器,自写着色器或Sprite Shader均可与此一起使用。您只需要a.albedo = c.rgb * IN.vert.color(此处为伪代码)

这意味着相同的着色器和相同的材质可用于具有不同顶点颜色的多个对象。那不会破坏批处理。

您甚至可以具有不同形状和顶点数的不同对象,为它们赋予不同的顶点颜色(每个顶点,例如渐变等),并且它仍将成批处理。

尽可能检查“静态”,将信息输入顶点颜色,对于移动的对象,尝试将它们保持在300 verts以下,以便可以进行动态批处理。

但是对于Sprites,统一为您自动完成此操作,您只需要使用SpriteRenderer-这就是为什么您不使用带有纹理的四边形,而是使用“ Sprite”和SpriteRenderer的原因。

再次,我可能是错的,SpriteRenderer实际上使用了MaterialPropertyBlocks,但是它的工作原理几乎相同。可以为每个对象设置这些变量,并且不会创建新的DrawCalls。变量值用于着色器中,因此多个对象的材质/着色器相同。