mcpField
U
urp-postprocessing

urp-postprocessing

github.com/unity-technologies开发58160 次安装6 天前更新
代码仓库

关于 urp-postprocessing

urp-postprocessing 是通过 Volume 框架设置、配置和调试 URP 后期处理效果的技能,面向在运行中的 Unity Editor 中操作项目的用户。它提供前置检查、代码指导、效果配方和故障排查步骤。

主要功能

  1. 01检查 URP 与相机前置条件
  2. 02配置 Volume 配置文件与覆盖项
  3. 03效果属性和 API 指导
  4. 04排查效果未生效的清单
  5. 05多种视觉风格的效果配方

适用场景

  1. 01设置全局或局部 Volume
  2. 02配置 Bloom 或 Color Adjustments
  3. 03诊断相机为何未应用 Volume
  4. 04实现电影、恐怖或清爽风格

安装

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

$npx skills add https://github.com/unity-technologies/unity-agent-plugin --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 和卡在 Safe Mode 中的 Editor,以及查找 Editor 的命令目录。请先遵循该技能;不要在这里重新推导这些内容。你特别需要 script eval,而不只是能够连接到 Editor:该命令是否存在取决于 Pipeline 包版本,而非 CLI。如果缺少该命令,请说明情况并停止。

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

向 script eval 传递 C#

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

  • 不能使用 using 指令。 编译器会将 using UnityEngine; 视为资源释放语句并拒绝它(CS0210)。
  • 类型必须写出完整限定名。 无法解析不带限定名的 AssetDatabase 或 Volume(CS0246/CS0103),而不带限定名的 Object 会与 object 产生歧义(CS0104)。

下面以文件形式编写的代码片段——为了便于阅读而包含 using,或是准备保存到项目中的代码——在传递给 script eval 前,都要为其中的类型补上限定名。

0. 预检

配置任何效果前,请确认所有检查均已通过。先修复未通过的项目。

  1. URP 是当前启用的渲染管线——如果不是,请告知用户并停止。
  2. URP Asset 已启用 HDR——色调映射需要 HDR。HDR 能让 Bloom 达到最佳效果;在 SDR 下 Bloom 仍可使用,但 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 包含在其中,否则摄像机将忽略该 Volume。
  5. Volume 已存在,且 enabled = true、配置文件有效,并至少包含一个覆盖项——Volume 组件必须已启用,且 profile(或 sharedProfile)不为 null,并至少有一个 VolumeComponent 的属性设置了 overrideState = true。
预检代码片段

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

// `script 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 组件的 GameObject,设置 isGlobal = true 并分配 profile。所有 volumeLayerMask 包含该 Volume 所在图层的摄像机都会受到影响。

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

  • 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。设置 value 之前,必须先设置 overrideState = true,否则 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 文件。传递给 script eval 的代码片段无法携带这些内容 — 请改为限定类型的命名空间(见上文“向 script 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 内?
  6. 相机的 data.renderType 是否为 CameraRenderType.Base,而不是 Overlay?(Overlay 相机会叠加到 Base 相机的输出上。)
  7. UniversalRenderPipeline.asset.supportsHDR 是否为 true?Bloom 和 Tonemapping 必须启用此项。
  8. 是否在 Game 视图中查看?Scene 视图的工具栏中有单独的后处理开关。

5. 常用配方

格式:效果 属性=值。Bloom 的值依次为 threshold/intensity/scatter。

电影感(影片): 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=warm shadows=cool

恐怖/阴暗: ColorAdjustments postExposure=-0.5 saturation=-30 contrast=20,Vignette intensity=0.5 smoothness=0.3 color=dark-red,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