Unity 着色器开发
JetBrains Rider 支持 Unity 着色器工作流程,包括从编写、代码分析到渲染帧检查和源级调试。 可以使用 Rider 的代码洞察、导航、重构和支持 Unity 的上下文工具编辑 ShaderLab .着色器 文件、CG/HLSL 代码块、共享 .cginc / .hlsl 包含文件以及计算着色器。
着色器支持概述
Rider 能识别 Unity 着色器相关文件并为其提供专用编辑器支持:
Unity ShaderLab .着色器 文件
ShaderLab 文件中嵌入的 CG/HLSL 着色器代码
着色器 include 文件,包括 Unity 专用的 .cginc 文件以及 HLSL include 文件,例如 .hlsl 和 .hlslinc
Unity 计算着色器( .compute )文件
在 ShaderLab 文件中,Rider 提供 语法和 错误高亮显示、 代码补全、 颜色辅助、 大括号匹配、 注释/撤消注释操作、 代码折叠、 路径导航、 文件结构、 实时模板 ,用于常见着色器构造, Search Everywhere 集成,以及着色器符号 导航。 ShaderLab 文件和独立 include 文件中的 HLSL 代码将结合 Unity 专用上下文进行分析,因此 Rider 可以理解着色器关键字、平台符号和 include 根目录。
创建和编辑着色器文件
使用 从 Rider 的 Unity 文件模板创建着色器文件。 Rider 提供多种常用着色器类型模板,包括:
不发光着色器
标准表面着色器
图像效果着色器

创建着色器后,可以在 Rider 中编辑 ShaderLab 声明、属性、Pass 和内嵌 CG/HLSL 代码。 代码洞察可跨越 ShaderLab 结构和内嵌着色器程序生效,因此可在 IDE 内进行补全、导航、高亮显示和格式设置。
处理着色器变体和关键字
处理着色器文件时,通常需要使用 #if 预处理程序指令来生成不同的 着色器变体 这些分支可用于为不同平台(如移动端或桌面)、不同图形 API(如 Vulkan 或 DirectX),或运行时通过 着色器关键字启用的不同用户功能引入条件行为。
Rider 会在输入时解析着色器源代码。 它会构建一个语义模型,并可用于提供丰富的功能,如语法高亮显示、 Ctrl+点击 导航、查找用法、智能重命名及其他重构功能。 然而,Rider 无法同时为所有预处理程序指令内容构建语义模型;不活跃分支可能包含现有字段或函数的冲突声明、损坏的代码,甚至可能包含意外的语法来关闭某个函数并声明新函数(例如,包含闭合大括号和新函数声明)。 因此,Rider 仅在编辑时根据当前已定义的符号分析预处理程序分支。 这会导致“未激活”的、置灰的预处理程序分支,没有语法高亮显示或检查。
Rider 允许选择启用哪些着色器关键字,以及定义哪些 Unity 着色器预处理程序符号
使用编辑器右上角的 变体 微件配置着色器分析上下文。 通过此微件,您可以:
选择图形 API,例如 DirectX 11、Vulkan、Metal、OpenGL Core、OpenGL ES 或 DirectX 11 功能级别 9.x。
在桌面和移动平台符号之间切换。
启用或禁用通过
#pragma shader_feature和#pragma multi_compile指令声明的着色器关键字。重置当前上下文或所有上下文的已启用关键字。

例如,选择 DirectX 11 会让 Rider 认为 SHADER_API_D3D11 符号已被定义, #if SHADER_API_D3D11 内的任何内容作为活动代码进行解析,并有语法高亮显示和检查。 切换到 Vulkan 意味着 SHADER_API_D3D11 不再处于激活状态,该预处理程序分支被视为未激活,但 #if SHADER_API_VULKAN 内的内容则处于激活状态。

同样,Rider 可以在桌面与移动端之间切换以激活 SHADER_API_DESKTOP 或 SHADER_API_MOBILE 符号。
所有已知的 SHADER_ 符号都会出现在代码补全弹窗中:

关键字高亮显示
Rider 会高亮显示着色器关键字,以展示当前变体如何影响代码分析:
由于选中了 启用的关键字 ,它们处于激活状态。
隐式启用的关键字 处于激活状态,因为 Unity 语义要求设置中的关键字必须有一个默认关键字。
已禁用的关键字 在当前变体中不活跃。
已禁止的关键字 已被选中但未激活,因为同一关键字设置中的另一个关键字具有更高优先级。
以下 #pragma 指令声明 BLUE、 RED 和 GREEN 着色器关键字。 这些关键字可通过 Shader.EnableKeyword API 在运行时启用(参见 着色器关键字文档了解更多)。
这些关键字也是预处理程序 define 符号,Rider 可通过着色器变体微件启用这些关键字,并处理相应的预处理程序分支。 启用关键字后,其会以粗体且带下划线高亮显示。
#pragma 中的关键字也会被高亮显示。 您也可以通过 Alt+Enter 上下文菜单,在 #pragma 或符号的使用处启用或禁用关键字。
Unity 允许多个关键字被启用,但 pragma 指令中只有第一个关键字被视为激活。 其他所有关键字都会被屏蔽并处于不活动状态。 Rider 会用删除线标记被屏蔽的关键字,同时符号不会被定义。 Rider 不会自动禁用 pragma 中的其他关键字,因为代码中可以启用多个冲突关键字,也可能在多个 pragma 中定义同一关键字。 可以在 Alt+Enter 菜单用于被抑制的关键字,以禁用导致其被抑制的关键字
如果某个分支不活跃,Rider 会显示 Code Vision 提示,指明该分支可能在其他着色器变体中活跃。 点击提示可以打开着色器关键字配置弹窗:

为共享 HLSL include 切换上下文
.hlsl shader 文件可以通过使用预处理程序符号和 #if 语句,在编译时通过更改方法和数据结构的定义、可用性或实现来修改行为。 分析这类文件时,Rider 默认采用自动上下文和默认定义的符号。 这可能导致 .hlsl 文件的部分被标记为非活动状态,无法使用 语法高亮显示、 代码补全、 检查等功能。
如果 .hlsl 文件被多个 .着色器 文件 include,或在同一 .着色器 文件的多个 CGPROGRAM 块中 include,则 Rider 可根据 include 点定义的上下文分析 .hlsl 文件。 可使用编辑器右上角的 上下文 微件切换上下文。
例如,假设有个文件 example.hlsl ,根据 FOO 符号是否定义来定义不同方法。 在 Auto 上下文下,Rider 默认 FOO 未定义,并将该 #if 语句的第一个分支标记为非活动状态。 此上下文下定义了 bar 函数,任何对 foo 函数的调用都会导致未解析符号错误。
再假设有一个 Foo.shader 文件定义了多个着色器程序,并在每个 CGPROGRAM 块中多次 include example.hlsl。 每个 Shader 程序都有自己的上下文。 第一个程序从第 14 行开始,先定义 FOO 符号再包含 example.hlsl ,第二个程序从第 22 行开始定义 BAR ,然后再包含 HLSL 文件。
编辑 example.hlsl 时,可以通过点击上下文选择器,从弹窗中选择 Shader 程序的位置来切换上下文。 Rider 会显示 Auto 上下文,同时列出包含 example.hlsl 的位置。 如果选择 Foo.shader:14 ,Rider 将使用第 14 行 Foo.shader 中 CGPROGRAM shader 的上下文分析 example.hlsl 文件。 也就是说,会定义 FOO 符号,上面 #if 语句的第一个分支会变为有效,并且会定义 foo 函数。

着色器名称和 Pass 名称支持
Rider 为 ShaderLab 文件中声明的着色器名称和 pass 名称提供代码洞察。 在 Shader 块中声明的着色器名称会在 回滚 命令中解析,pass 名称会在 UsePass 命令中解析。 Rider 针对这些引用提供补全、 Ctrl+B 导航、 Alt+F7 和 Shift+F6 功能。 重命名 pass 时,Rider 会确保 UsePass 引用使用所需的大写格式设置。
着色器名称也会在 C# 代码中解析。 如在 C# 脚本中使用 Shader.Find ,Rider 会针对着色器名称提供补全、导航、查找用法和重命名支持。
HLSL 功能
Rider 为 ShaderLab 文件和独立 HLSL include 文件中的 HLSL 代码提供额外功能:
Rider 解析
#pragma surface和#pragma vertex指令中的方法名称,若引用的方法未声明,则高亮显示错误。#pragma指令参数支持代码补全。包虚拟文件夹在#include语句中受支持,并且支持对来自项目软件包和软件包缓存的文件进行补全及导航。UNITY_VERSION预定义宏在分析时可被识别。 悬停宏可查看其当前值,取决于项目所用 Unity 版本。
导航、搜索和重构着色器代码
Rider 会为着色器文件及相关 HLSL 代码构建语义模型。 具体启用的功能取决于当前激活的分析上下文:
从着色器引用定位到声明 Ctrl+B
查找支持的着色器符号用法 Alt+F7
为着色器与 HLSL 符号重命名重构 Shift+F6
ShaderLab 命令快速文档 Ctrl+Q
Search Everywhere 搜索着色器符号和文件结果
ShaderLab 结构的路径导航
对于依赖于 #if、 #ifdef、 shader_feature 或 multi_compile 分支的着色器代码,需首先确认激活的变体。 导航和分析会依据当前选中的 着色器上下文。
使用 Frame Viewer 查看器调试着色器
Frame Viewer 工具 可直接在 IDE 中打开 RenderDoc .rdc 快照。 可用其检查渲染行为并调试图形问题,无需切换到其它工具。
使用 Frame Viewer 查看器,你可以:
打开并检查 .rdc 渲染快照。
在结构化树中导航绘制调用。
根据着色器源用法筛选器筛选绘制调用。
检查顶点数据、输入、输出和纹理。
展开纹理预览。
针对选定顶点或像素启动着色器调试。
设置断点,并逐步执行映射到的着色器源代码。
调试 Unity 着色器
在要调试的着色器程序中添加
#pragma enable_d3d11_debug_symbols。使用 RenderDoc 从 Unity 捕获帧。
点击 Rider 窗口右侧边栏中的 Frame Viewer 查看器图标,并在该处打开 .rdc 快照。
选择一个绘制调用。
使用 调试 Pixel 或 调试顶点。
在 Rider 调试器中逐步执行着色器。

Rider 会在可能的情况下将调试会话映射回原始 ShaderLab 源代码,包括 .着色器 文件和 .cginc 包含文件中的源代码范围。 当原始源映射不可用时,Rider 可以退回到生成或反汇编的着色器代码。
故障排除
着色器分支被置灰
打开 Variants 微件 ,并检查所需的关键字、图形 API 或平台符号是否已启用。 分支高亮显示会跟随所选的着色器变体上下文。
关键字已启用但显示为已屏蔽
检查相应的 #pragma shader_feature 或 #pragma multi_compile 指令。 如果同一关键字设置中的多个关键字被启用,Unity 只会将其中一个视为激活。 Rider 会将剩余启用的关键字显示为已屏蔽。
在共享 include 文件中补全或检查结果不正确
使用 上下文微件 选择包含该文件的着色器程序。 共享的 .hlsl 和 .cginc 文件根据所包含的着色器和 Pass 可能有不同的活动分支。
着色器调试未启动
请检查:
正在 Windows 上使用 Rider。
Frame Viewer 查看器插件已启用。
该项目以 Unity 项目的方式打开。
.rdc 快照已成功加载。
着色器是在带有调试符号的情况下捕获的,例如使用
#pragma enable_d3d11_debug_symbols。
如果快照加载失败,请使用受支持的 RenderDoc 版本重新捕获。 Direct3D 12 捕获可能需要 RenderDoc 1.33。
调试器导航打开的是生成的着色器代码而不是原始 ShaderLab
Rider 基于捕获中的源代码行信息,将生成的着色器代码映射回原始源文件。 如果原始文件缺失、在捕获后有重大更改,或者由于宏展开差异无法匹配,Rider 可能会退回到生成或反汇编的代码。 保存当前着色器源文件后重新捕获帧。
Unity 资源用法或序列化值不可用
Unity 资源用法和序列化字段 Code Vision 数据取决于资源索引。 请确保 Unity 项目使用基于文本的资源序列化,并等待初始资源索引完成。