Version: 2020.1
Using materials with C# scripts
基于物理的渲染材质验证器

Scripting for materials that use the Standard Shader

In the Built-in Render Pipeline, the Standard Shader has some extra requirements if you want to modify materials at runtime.

This is because - behind the scenes - the Standard Shader is actually many different shaders rolled into one. These different types of shader are called Shader Variants and can be thought of as all the different possible combinations of the shader’s features, when activated or not activated.

例如,如果您为材质设置了一个法线贴图,就会激活支持法线贴图的着色器变体。如果随后又设置了高度贴图,就会激活同时支持法线贴图和高度贴图的着色器变体。

This is a good system, because it means that if you use the Standard Shader, but do not use a Normal Map in a certain material, you are not incurring the performance cost of running the Normal Map shader code - because you are running a variant of the shader with that code omitted. It also means that if you never use a certain feature combination (such as HeightMap & Emissive together), that variant is completely omitted from your build - and in practice you will typically only use a very small number of the possible variants of the Standard Shader.

Unity avoids simply including every possible shader variant in your build, because this would be a very large number, some tens of thousands! This high number is a result not only of each possible combination of features available in the material Inspector, but also there are variants of each feature combination for differing rendering scenarios such as whether or not HDR is being used, lightmaps, GI, fog, etc. Including all of these would cause slow loading, high memory consumption, and increase your build size and build time.

所以 Unity 的替代方案是:通过检查项目中使用的材质资源来追踪您使用过的着色器变体。无论在项目中加入了哪些标准着色器变体,这些变体都会包含在构建中。

这个方案在通过脚本访问标准着色器材质的情况下,存在两个问题。

1.您必须为所需的标准着色器变体启用正确的关键字

If you use scripting to change a material that would cause it to use a different variant of the Standard Shader, you must enable that variant by using the EnableKeyword function. A different variant would be required if you start using a shader feature that was not initially in use by the material. For example assigning a Normal Map to a Material that did not have one, or setting the Emissive level to a value greater than zero, when it was previously zero.

用来启用标准着色器功能的关键字如下:

关键字 功能
_NORMALMAP 法线贴图
_ALPHATEST_ON “镂空”透明度渲染模式
_ALPHABLEND_ON “淡化”透明度渲染模式
_ALPHAPREMULTIPLY_ON “透明”透明度渲染模式
_EMISSION 发射颜色发射贴图
_PARALLAXMAP 高度贴图
_DETAIL_MULX2 辅助“细节”贴图(反照率和法线贴图)
_METALLICGLOSSMAP 金属性工作流程中的金属性/平滑度贴图
_SPECGLOSSMAP 镜面反射工作流程中的镜面反射/平滑度贴图

使用上面的关键字足以让您的材质修改脚本在编辑器运行模式中起效。

但是,由于 Unity 仅通过检查项目中使用的材质来确定要在构建中包含哪些变体,因此它不会包含在运行时通过脚本使用到的变体。

这就是说,如果您在脚本中为材质启用 _PARALLAXMAP 关键字,但是项目中未使用与该功能组合匹配的材质,则视差贴图将无法在最终构建中生效(即使在编辑器中看起来正常)。这是因为构建过程将会忽略该变体,因为它看起来不是必需的。

2.您必须确保 Unity 在构建中包含所需的着色器变体

为此,您需要确保 Unity 知道您要使用该着色器变体,具体方法就是在资源中包含至少一个该类型的材质。该材质必须应用在场景中,或者也可以将其放入 Resources 文件夹,否则该材质处于未使用状态,Unity 仍会在构建中忽略它。

通过完成上述两个步骤,即可在运行时使用标准着色器修改材质。

如果您有兴趣了解有关着色器变体的详细信息以及如何构建自己的变体,请阅读制作多个着色器程序变体的信息

Using materials with C# scripts
基于物理的渲染材质验证器