从我在Unity开发中的第一天开始,我就看到了一些技巧和内容,说我们永远不应该打造精灵 . 如果我们想要不同颜色的精灵,创建它们并将它们放在相同的纹理中,然后交换不同颜色的精灵 .
原因是着色精灵会破坏配料 .
我创建了一个小型演示 .
Situation 1
在6个游戏对象中使用相同的方形精灵 . 这里不足为奇 . 在统计数据中,有1批 . 5通过批处理保存 .
Situation 2
同样的方形精灵再次用于6个游戏对象,但这一次,所有这些都用红色着色,颜色值相同 .
Shouldn't this be breaking batching already?
Situation 3
为了完整起见,我用不同的颜色着色了方形精灵 . 尽管如此,我们仍然有1批次,5个已保存 . 什么都没有改变 .
Additional information
-
我在一场比赛中 grab 了情况1和2,并且在单独的比赛中 grab 了情况3 .
-
我尝试通过更改
SpriteRenderer.color
更改SpriteRenderer
和 through scripts 的"Color"字段来调整精灵 directly in the editor . 结果是一样的 .
2 回答
更改
SpriteRenderer
组件上精灵的颜色不应该是材质,甚至当您尝试使用SpriteRenderer.material
属性访问材质时 .例如,
这 breaks 批处理:
因为您正在访问该材料 . 第一次访问材料属性时,它将创建新的材质实例 .
这 will not 打破批处理:
它不会,因为它没有访问
material
属性 . 即使它不会破坏批处理,但它的一个问题是性能 . 执行此操作时会影响性能 .AFAIK,着色基本上是设置顶点颜色 . 这是针对粒子完成的,您可以在其中设置随机起始颜色,并且所有粒子都在单个绘制调用中呈现 . 顶点颜色不会更改/创建新材质 .
不确定早期的Unity版本是如何处理的,但精灵应该是简单的四边形,因此支持顶点颜色 . Sprite着色器可能在着色方面的工作方式相同 .
一般来说,你是对的 . 更改着色器属性将创建该材质的副本,或者它将更改材质本身并影响使用该材质的所有实例 . 你是否在精灵材质或spriteRenderer上使用了色调?
手工,我可以想到使用MaterialPropertyBlocks,但也许Unity确实为精灵做了 .
更多细节澄清:
A 你有"Material01.mat" - 它是绿色的 . 您将此材料复制到10个精灵 . 你想要10种颜色?你必须创建10种材料,每种材料都有所需的颜色 - 10个Draw调用 .
您可以通过脚本执行相同操作,只需更改material.color即可 . 但Unity将为您复制材料 . 还有10个Draw电话 . 有些人很困惑,为什么在他们听到这个之前打破批处理 .
B 您更改了RENDERERs色调 . 这个Sprite渲染器会使用顶点颜色属性将色调颜色写入精灵顶点(可能是4?) . 它基本上是免费的,因为无论如何它们都被传送到gpu(afaik)
如上所述,在粒子系统中使用相同的方法,允许彩虹粒子具有1个Drawcall .
因此,任何粒子着色器,自写着色器或Sprite着色器都应该使用它 . 你需要的只是
a.albedo = c.rgb * IN.vert.color
(这里有点伪代码)这意味着,相同的着色器和相同的材质可用于具有不同顶点颜色的多个对象 . 这不会打破批处理 .
您甚至可以拥有任何形状和顶点数的不同对象,为它们提供不同的顶点颜色(每个顶点,如渐变等),它仍然会批处理 .
尽可能检查静态,将信息提供给顶点颜色,对于移动对象,尝试将它们保持在300个顶点以下,这样动态批处理就可以工作 .
但是对于Sprites来说,Unity会为你自动化,你只需要使用SpriteRenderer - 这就是为什么你不使用带有纹理的四边形,而是使用“Sprite”和SpriteRenderer .
再次,我可能是错的,SpriteRenderer实际上使用MaterialPropertyBlocks,但它的工作方式几乎相同 . 可以为每个对象设置这些变量,而不创建新的DrawCall . 变量值在着色器中使用,因此材质/着色器对于多个对象是相同的 .