简答
不要这样做。通过游戏对象的渲染器分配更改material 的shader 属性会导致创建材质的多个实例,这不仅计算成本高,而且在GPU 上的内存方面也很昂贵。
Thomas of Unity 教程说得最好:
最有可能跳入您脑海的第一件事是:
GetComponent<Renderer>().material.color = ...
很简单,对吧?只需抓住该颜色并设置动画即可。这样做的问题是,为了改变着色器中的颜色,Unity 需要告诉 GPU 这个对象将以不同的方式渲染,而唯一的方法就是改变材质实例。因此,当您第一次访问 renderer.material 时,Unity 会创建一个材质的副本。
这意味着可能有大量素材副本,所有吃掉记忆1
2500 个球体共享相同材质的场景。其他 39 种材质用于场景中的其他项目。 1
1
在 2500 个对象上摆弄 GameObject.renderer.material.shader 之后。请注意材料是如何从 40 到 2540 个材料跃升的!
1
长答案
首先复习一下。在 Unity 中,您创建(或从 Asset Store 购买)着色器,然后创建材质。然后,材质指的是着色器,它提供着色器可能需要的任何参数,例如纹理;凹凸贴图;和标量,可以将此材质与可能使用相同着色器的任何其他材质区分开来。完成后,您可以将材质应用于对象。
我的意思是在同一个游戏对象上的着色器之间切换
所以想要切换着色器并没有什么意义。对象直接与着色器对话不仅不正确,而且它没有足够的细节供着色器这样做。
您想要做的是切换材质在一个对象上而不是。
如果我在游戏运行时在着色器之间切换,它不会生效
没有看到你的代码,很难说。无论如何,您最好提前定义所有资产,而不是动态创建。通过这种方式,您可以为已知的保真度或平台烘焙它,而无需代码决定应该使用哪个着色器级别。
解决方法
如果您必须在运行时更改材质,您可能需要考虑 Unity 的 MaterialPropertyBlock。
MaterialPropertyBlock 由 Graphics.DrawMesh 和 Renderer.SetPropertyBlock 使用。在您想用相同的材料绘制多个对象但属性略有不同的情况下使用它。例如,如果您想稍微改变绘制的每个网格的颜色。不支持更改渲染状态More...
不幸的是,您现在需要将 PerRendererData 添加到您的着色器中,Thomas 在下面的文章中对此进行了解释。
这么简单的事情有很多复杂性。提前准备好预先设计好的材料要好得多。这可以说是一种更好的做法。
告诉我更多
-
优秀文章THE MAGIC OF MATERIAL PROPERTY BLOCKS
-
"Change the color of a material for only one object",Answers, Unity