mcpField
U
urp-postprocessing

urp-postprocessing

github.com/unity-technologies创意与媒体1.2k6.1k 次安装1 天前更新
代码仓库

关于 urp-postprocessing

使用 URP 的 Volume 框架配置和调试后处理效果的 Unity 技能。它提供实时编辑器检查、设置指导、效果参考和常见视觉风格配方。

主要功能

  1. 01检查 URP、HDR、相机和 Volume 前置条件
  2. 02配置全局及局部 Volume 和配置文件
  3. 03通过 VolumeComponent 覆盖项添加效果
  4. 04提供代码模板和视觉风格配方
  5. 05排查相机与 Volume 配置

适用场景

  1. 01在 Unity 场景中设置 Bloom 或 Tonemapping
  2. 02创建按距离混合的局部效果
  3. 03诊断 Game 视图中后处理效果缺失

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/unity-technologies/skills --skill urp-postprocessing

安装后在 Claude Code 中输入/urp-postprocessing确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

SECURITY.md
references/
code-templates.md
effect-reference.md

详细介绍

帮助用户使用 URP 的 Volume 框架设置、配置和调试后处理效果。

目标:设置完成后,用户应获得可正常工作的视觉效果,且控制台中没有错误。

0. 前提条件:可运行 C# 的 Editor

Volume 配置文件、VolumeParameter.overrideState 和摄像机的后处理标志都属于 Editor/运行时对象状态——以下检查和编辑都需要在运行中的 Editor 内执行 C#。

unity-cli 技能负责带你完成这些步骤——安装 CLI、确认已连接的 Editor、添加项目的 com.unity.pipeline 包、区分确实缺少 Editor 和 Editor 卡在安全模式这两种情况,以及发现 Editor 的命令目录。请先按其说明操作;此处不再重复这些内容。你尤其需要 eval,而不仅仅是能连接到 Editor:它是否存在取决于 Pipeline 包版本,而不是 CLI。如果缺少 eval,请说明这一点并停止。

使用 eval 命令通过已连接的 Editor 运行 C#。请通过 unity command --format json 查明其参数形式,不要自行假设——内联形式为 unity command eval --code '<snippet>',某些 Pipeline 版本也会注册 eval_file,用于从文件运行代码片段。使用 eval_file 前请先检查命令目录;它经常不存在。unity command 默认超时时间为 30 秒。

向 eval 传递 C#

eval 编译的是语句块,而不是文件。这会带来两个后果,且都会导致编译错误,而非警告:

  • 不能使用 using 指令。 编译器会将 using UnityEngine; 视为资源释放语句并拒绝编译(CS0210)。
  • 类型必须使用完全限定名。 单独写 AssetDatabase 或 Volume 无法解析(CS0246/CS0103),而单独写 Object 会与 object 冲突(CS0104)。

如果下面的代码片段以文件形式编写——包含 using 语句以便阅读,或因为它要保存到项目中——请先将类型改为完全限定名,再传给 eval。

0. 预检

配置任何效果之前,请验证所有检查项。先修复失败项。

  1. URP 是当前使用的渲染管线——如果不是,请告知用户并停止。
  2. URP Asset 已启用 HDR——Tonemapping 需要 HDR。Bloom 在 HDR 下效果最佳;在 SDR 下仍可使用,但 threshold 必须小于 1。
  3. 摄像机已启用后处理——renderPostProcessing 必须为 true(默认值为 false)。摄像机堆叠:只有 CameraRenderType.Base 摄像机(或堆叠中的最后一个 Overlay)应启用后处理。还要确认 Renderer 的 PostProcessData 资源不为 null——如果为 null,后处理通道将不存在。
  4. Volume 的 GameObject 图层包含在摄像机的 Volume Layer Mask 中——volumeLayerMask 默认仅包含图层 0“Default”。必须包含 Volume 的 GameObject.layer,否则摄像机将忽略它。
  5. Volume 存在,且 enabled = true、配置文件有效,并至少有一个覆盖项——Volume 组件必须已启用,具有非空的 profile(或 sharedProfile),并且至少有一个 VolumeComponent 的属性设置了 overrideState = true。
预检代码片段

运行以下代码,以程序方式验证设置:

// `eval` compiles a statement block, not a file: no `using` directives are
// allowed, so every type is fully qualified.
var report = new System.Text.StringBuilder();

// 1. Check URP is active — a hard stop, so throw: it fails the eval loudly
var urpAsset = UnityEngine.Rendering.Universal.UniversalRenderPipeline.asset;
if (urpAsset == null)
    throw new System.Exception("URP is not the active render pipeline.");

// 2. Check HDR
if (!urpAsset.supportsHDR)
    report.AppendLine("Warning: HDR is disabled on the URP Asset. Tonemapping won't work; Bloom requires threshold < 1.");

// 3. Check camera post-processing
var cam = UnityEngine.Camera.main;
if (cam == null)
    throw new System.Exception("No Main Camera found.");
if (!cam.TryGetComponent<UnityEngine.Rendering.Universal.UniversalAdditionalCameraData>(out var camData))
    throw new System.Exception("Missing UniversalAdditionalCameraData on camera. Is URP active?");
if (!camData.renderPostProcessing)
    report.AppendLine("Warning: Post-processing is disabled on the camera. Enable via camData.renderPostProcessing = true.");

// 4. Check volume layer mask
var volumes = UnityEngine.Object.FindObjectsByType<UnityEngine.Rendering.Volume>(UnityEngine.FindObjectsSortMode.None);
foreach (var vol in volumes)
{
    if (!vol.enabled) { report.AppendLine($"Warning: Volume '{vol.name}' is disabled."); continue; }
    if ((camData.volumeLayerMask & (1 << vol.gameObject.layer)) == 0)
        report.AppendLine($"Warning: Volume '{vol.name}' on layer {vol.gameObject.layer} is not in camera's volumeLayerMask.");
    // 5. Check profile and overrides
    var profile = vol.sharedProfile;
    if (profile == null) { report.AppendLine($"Warning: Volume '{vol.name}' has no profile assigned."); continue; }
    if (profile.components.Count == 0)
        report.AppendLine($"Warning: Volume '{vol.name}' profile has no overrides.");
}

// Return the findings: logs land in the Editor console, the returned value comes back to you
return report.Length == 0 ? "Post-processing setup looks correct." : report.ToString();

1. Volume 设置

通过 VolumeProfile(一个 ScriptableObject)上的 VolumeComponent 覆盖项来添加效果。

全局 Volume(最常见):包含 Volume 组件、设置了 isGlobal = true 并分配了 profile 的 GameObject。会影响所有 volumeLayerMask 包含该 Volume 所在图层的摄像机。

局部 Volume(可选,但优先级更高):包含触发器 Collider 和 Volume 组件、设置了 isGlobal = false 的 GameObject。属性:

  • priority(float)——数值越高,在 Volume 重叠时覆盖优先级越低的 Volume。
  • blendDistance(float)——开始混合的外部距离,单位为世界单位(0 = 不混合,在 Collider 边界处立即切换)。
  • weight(float,0–1)——缩放 Volume 的整体影响。

2. 后期处理效果

所有效果都是 VolumeComponent 子类,通过 profile.Add<T>() 作为覆盖项添加到 VolumeProfile。使用 profile.Has<T>() 或 profile.TryGet<T>(out var t) 检查是否存在。使用 profile.Remove<T>() 移除。

每个属性都是一个 VolumeParameter。必须先将 overrideState = true,再设置 value,否则 Volume 系统会忽略它。

配置特定效果时,请加载完整的 API 参考:

  • references/effect-reference.md — 各效果的所有 VolumeComponent 属性(Bloom、Tonemapping、ColorAdjustments、DepthOfField、Vignette、MotionBlur、FilmGrain、ChromaticAberration、SplitToning、LensDistortion、WhiteBalance、PaniniProjection、LiftGammaGain、ShadowsMidtonesHighlights、ColorCurves、ChannelMixer)

代码模板:

3. 防幻觉规则

必需的 Usings

这些适用于在项目中编写 .cs 文件的情况。传递给 eval 的代码片段无法包含这些内容——请改为限定类型名称(参见上文“向 eval 传递 C# 代码”)。

using UnityEngine.Rendering;           // Volume, VolumeProfile, VolumeComponent, VolumeParameter
using UnityEngine.Rendering.Universal;  // Bloom, Tonemapping, ColorAdjustments, UniversalRenderPipeline, etc.
错误 → 正确的 API 映射
错误正确
PostProcessVolumeVolume(来自 UnityEngine.Rendering)
PostProcessLayerUniversalAdditionalCameraData.renderPostProcessing(bool)
UnityEngine.Rendering.PostProcessingUnityEngine.Rendering.Universal
profile.GetSetting<T>()profile.TryGet<T>(out var t)(返回 bool)
profile.AddSettings<T>()profile.Add<T>()(返回 T;若已存在则抛出异常——请先检查 profile.Has<T>())
volume.sharedProfile(用于运行时修改)volume.profile(自动将资源克隆为实例)
VolumeManager.instance.stack.GetComponent<T>()volume.profile.TryGet<T>(out var t)
关键事实
  • 对你设置的每个 VolumeParameter,都必须设置 overrideState = true。Volume 系统会跳过 overrideState 为 false 的参数。这是脚本编写中最常见的错误。
  • sharedProfile = 直接返回资源(编辑会持久保存到磁盘)。profile = 必要时自动克隆为实例(适用于安全地进行运行时编辑)。使用 volume.HasInstantiatedProfile() 检查。
  • profile.Add<T>(bool overrides = false) — 传入 true 可自动启用所添加组件所有参数的 overrideState。

4. 调试清单

后期处理不起作用时,请按顺序检查:

  1. cam.TryGetComponent<UniversalAdditionalCameraData>(out var data) 是否成功,且 data.renderPostProcessing 是否为 true?
  2. 场景中是否存在 Volume,且已分配非空的 profile(或 sharedProfile)?
  3. 是否通过 profile.Add<T>() 添加了覆盖项,并为你设置的每个属性设置了 overrideState = true?
  4. Volume 的 GameObject.layer 是否包含在摄像机的 data.volumeLayerMask 中?(默认遮罩仅包含第 0 层“Default”。)
  5. 是否设置了 volume.isGlobal = true(全局 Volume),或摄像机是否位于 Volume 的触发器 Collider 内(局部 Volume)?
  6. 摄像机的 data.renderType 是否为 CameraRenderType.Base,而不是 Overlay?(Overlay 摄像机会合成到 Base 摄像机的输出上。)
  7. UniversalRenderPipeline.asset.supportsHDR 是否为 true?Bloom 和 Tonemapping 需要此设置。
  8. 是否正在 Game 视图中查看?Scene 视图工具栏中有单独的后期处理开关。

5. 常用配方

格式:效果 属性=值。Bloom 的值依次为阈值/强度/散射。

电影感(胶片): Tonemapping mode=ACES,ColorAdjustments contrast=15 saturation=-10,Bloom threshold=0.9 intensity=0.5 scatter=0.7,Vignette intensity=0.3 smoothness=0.4,FilmGrain type=Medium1 intensity=0.2

风格化/鲜艳: Tonemapping mode=Neutral,ColorAdjustments saturation=20 contrast=10,Bloom threshold=0.8 intensity=1.5 scatter=0.6,SplitToning highlights=暖色 shadows=冷色

恐怖/暗黑: ColorAdjustments postExposure=-0.5 saturation=-30 contrast=20,Vignette intensity=0.5 smoothness=0.3 color=暗红色,FilmGrain type=Large01 intensity=0.4,ChromaticAberration intensity=0.15

清爽/移动端: Tonemapping mode=Neutral,ColorAdjustments postExposure=0.2,Bloom threshold=1.0 intensity=0.3(微妙效果)。移动端避免使用 FilmGrain、MotionBlur、DepthOfField。

6. 最终确认

设置完成后,向用户报告:

Post-Processing Setup Complete
- Volume: [Global/Local] on "[GameObject Name]"
- Profile: [Asset Path]
- Effects: [List with key property=value pairs]
- Camera: [Name] — renderPostProcessing=true, volumeLayerMask includes layer [N]

View results in Game view (not Scene view).
Undo all changes with Edit > Undo (Ctrl+Z).

评论

支持 Markdown