首页 文章

有色精灵是否真的在较新版本的Unity中进行批量处理?

提问于
浏览
2

从我在Unity开发中的第一天开始,我就看到了一些技巧和内容,说我们永远不应该打造精灵 . 如果我们想要不同颜色的精灵,创建它们并将它们放在相同的纹理中,然后交换不同颜色的精灵 .

原因是着色精灵会破坏配料 .

我创建了一个小型演示 .


Situation 1

Situation 1

在6个游戏对象中使用相同的方形精灵 . 这里不足为奇 . 在统计数据中,有1批 . 5通过批处理保存 .


Situation 2

Situation 2

同样的方形精灵再次用于6个游戏对象,但这一次,所有这些都用红色着色,颜色值相同 .

Shouldn't this be breaking batching already?


Situation 3

Situation 3

为了完整起见,我用不同的颜色着色了方形精灵 . 尽管如此,我们仍然有1批次,5个已保存 . 什么都没有改变 .


Additional information

  • 我在一场比赛中 grab 了情况1和2,并且在单独的比赛中 grab 了情况3 .

  • 我尝试通过更改 SpriteRenderer.color 更改 SpriteRendererthrough scripts 的"Color"字段来调整精灵 directly in the editor . 结果是一样的 .

2 回答

  • 4

    更改 SpriteRenderer 组件上精灵的颜色不应该是材质,甚至当您尝试使用 SpriteRenderer.material 属性访问材质时 .

    例如,

    breaks 批处理:

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

    因为您正在访问该材料 . 第一次访问材料属性时,它将创建新的材质实例 .


    will not 打破批处理:

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

    它不会,因为它没有访问 material 属性 . 即使它不会破坏批处理,但它的一个问题是性能 . 执行此操作时会影响性能 .

  • 3

    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 . 变量值在着色器中使用,因此材质/着色器对于多个对象是相同的 .

相关问题