每次构建项目时,Unity 编辑器都会编译构建所需的所有着色器:针对每个所需的图形 API 编译每个所需的着色器变体。
当您在 Unity 编辑器中工作时,编辑器不会提前编译所有内容。这是因为为每个图形 API 编译每个变体可能需要很长时间。
相反,Unity 编辑器会这样做:
Library/ShaderCache
文件夹。着色器编译使用名为 UnityShaderCompiler
的进程。可启动多个 UnityShaderCompiler
编译器进程(通常在机器中每个 CPU 核心对应一个),这样在播放器构建时就可以并行完成着色器编译。当编辑器不编译着色器时,编译器进程不执行任何操作,也不消耗计算机资源。
如果有许多经常更改的着色器,着色器缓存文件夹可能会变得非常大。删除此文件夹是安全的;只会导致 Unity 重新编译着色器变体。
在播放器构建时,所有“尚未编译”的着色器变体都将被编译,因此即使编辑器不会使用这些着色器变体,它们也会存在于游戏数据中。
不同平台使用不同的着色器编译器来编译着色器程序,如下所述:
使用 pragma 指令可以配置各种着色器编译器设置。
着色器编译涉及几个步骤。首先,需要进行预处理。在此步骤中,一个名为预处理器的程序为编译器准备着色器源代码。
在 Unity 的早期版本中,编辑器使用了当前平台着色器编译器提供的预处理器。现在,您可以选择是使用 Unity 的缓存着色器预处理器,或者采用之前的方法。除非遇到问题,否则应该使用缓存着色器预处理器。
缓存着色器预处理器是为快速编译而优化的着色器预处理器,速度提高了 25%。它缓存中间预处理数据,因此编辑器只需要在内容更改时解析 include 文件。这使得编译同一着色器的多个变体更加高效。当项目中的着色器使用大量常见 include 文件时,启用缓存着色器预处理器具有最明显的效果。
除了提高性能,缓存着色器预处理器还增加了以下功能:
#pragma
指令。#pragma warning
指令。#include_with_pragmas
指令,允许您将 #pragma
指令放在 include 文件中。有关缓存着色器预处理器和以前行为之间差异的详细信息,请参阅 Unity 论坛:新着色器预处理器 (New shader preprocessor)。
您可以使用 Editor settings 窗口的 Shader Compilation 部分中的 Caching Shader Preprocessor 复选框,或者使用 EditorSettings.cachingShaderPreprocessor API,启用或者禁用缓存着色器预处理器。
在构建游戏时,Unity 可能检测到游戏不使用某些内部着色器变体,并从构建数据中排除(“剥离”)它们。构建时剥离将用于以下各项:
#pragma shader_feature
的着色器,Unity 会自动检查是否使用了变体。如果构建中的材质都不使用某个变体,则该变体不会包含在构建中。请参阅内部着色器变体文档。标准着色器会使用此功能。上述的组合通常会大大减小着色器数据大小。例如,完全编译后的标准着色器将占用几百兆字节,但在典型的项目中,通常最终仅占用几兆字节(并且通常会由应用程序打包过程进一步压缩)。