urp-postprocessing

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
Help the user set up, configure, and debug post-processing effects using URP's Volume framework.
Goal: The user should have a working visual result with zero console errors after setup.
帮助用户使用URP的Volume框架设置、配置和调试后期处理效果。
目标:设置完成后,用户应获得可正常运行的视觉效果,且控制台无任何错误。

0. Prerequisite: an Editor you can run C# in

0. 前提条件:可运行C#的编辑器

Volume profiles,
VolumeParameter.overrideState
, and the camera's post-processing flags are Editor/runtime object state — the checks and edits below all run C# inside a live Editor.
The
unity-cli
skill owns getting you there
— installing the CLI, confirming a connected Editor, adding the project's
com.unity.pipeline
package, telling a genuinely absent Editor apart from one stuck in Safe Mode, and discovering the Editor's command catalog. Follow it first; don't re-derive any of it here. You need
eval
in particular, not just a reachable Editor: its presence depends on the Pipeline package version, not on the CLI. If it's missing, say so and stop.
Run C# through the connected Editor with the
eval
command. Discover its parameter shape from
unity command --format json
rather than assuming one — the inline form is
unity command eval --code '<snippet>'
, and some Pipeline versions also register
eval_file
for running a snippet from a file. Check the catalog before reaching for
eval_file
; it is frequently absent.
unity command
defaults to a 30 second timeout.
Volume配置文件、
VolumeParameter.overrideState
以及相机的后期处理标志均为编辑器/运行时对象状态——以下所有检查和编辑操作均在实时编辑器中运行C#代码。
unity-cli
技能负责帮你达成这一前提
——安装CLI、确认已连接编辑器、添加项目的
com.unity.pipeline
包、区分真正不存在的编辑器与卡在安全模式的编辑器,以及发现编辑器的命令目录。请先遵循该技能的指引;此处请勿重复推导相关内容。你尤其需要
eval
功能,而不仅仅是可连接的编辑器:该功能的存在取决于Pipeline包版本,而非CLI。如果缺少该功能,请告知用户并停止操作。
使用
eval
命令通过已连接的编辑器运行C#代码。请通过
unity command --format json
查看其参数格式,而非自行假设——内联形式为
unity command eval --code '<snippet>'
,部分Pipeline版本还注册了
eval_file
用于运行文件中的代码片段。在使用
eval_file
前请先检查命令目录;该功能经常不存在。
unity command
默认超时时间为30秒。

Passing C# to
eval

eval
传递C#代码

eval
compiles a statement block, not a file. Two consequences, both of which cause a compile error rather than a warning:
  • No
    using
    directives.
    The compiler reads
    using UnityEngine;
    as a resource-disposal statement and rejects it (
    CS0210
    ).
  • Types must be fully qualified. A bare
    AssetDatabase
    or
    Volume
    does not resolve (
    CS0246
    /
    CS0103
    ), and a bare
    Object
    is ambiguous with
    object
    (
    CS0104
    ).
Where a snippet below is written as a file — with usings, for readability, or because it is meant to be saved into the project — qualify the types before passing it to
eval
.
eval
编译的是语句块,而非文件。这会导致两个后果,均会引发编译错误而非警告:
  • 不支持
    using
    指令
    。编译器会将
    using UnityEngine;
    视为资源释放语句并拒绝执行(错误码
    CS0210
    )。
  • 类型必须完全限定。未限定的
    AssetDatabase
    Volume
    无法解析(错误码
    CS0246
    /
    CS0103
    ),未限定的
    Object
    会与
    object
    产生歧义(错误码
    CS0104
    )。
若下方的代码片段是以文件形式编写的——包含
using
指令以提升可读性,或旨在保存到项目中——请在传递给
eval
前先对类型进行限定。

0. Pre-Flight Checks

0. 预检检查

Before configuring any effect, verify all checks. Fix failures first.
  1. URP is the active render pipeline — If not, inform the user and stop.
  2. HDR is enabled on the URP Asset — Required for Tonemapping. Bloom works best with HDR; in SDR it still works but
    threshold
    must be < 1.
  3. Camera has post-processing enabled
    renderPostProcessing
    must be
    true
    (defaults to
    false
    ). Camera Stacking: only a
    CameraRenderType.Base
    camera (or the last
    Overlay
    in the stack) should enable post-processing. Also verify the Renderer's PostProcessData asset is not null — if it is, the post-process pass won't exist.
  4. The Volume's GameObject layer is in the Camera's Volume Layer Mask
    volumeLayerMask
    defaults to layer 0 "Default" only. The Volume's
    GameObject.layer
    must be included, otherwise the camera ignores it.
  5. Volume exists with
    enabled = true
    , a valid Profile, and at least one override
    — The
    Volume
    component must be enabled, have a non-null
    profile
    (or
    sharedProfile
    ), and at least one
    VolumeComponent
    with
    overrideState = true
    on its properties.
在配置任何效果之前,请完成所有检查。先修复检查不通过的项。
  1. URP为当前激活的渲染管线——若不是,请告知用户并停止操作。
  2. URP资源已启用HDR——这是色调映射的必要条件。Bloom在HDR下效果最佳;在SDR模式下仍可工作,但
    threshold
    必须小于1。
  3. 相机已启用后期处理——
    renderPostProcessing
    必须设为
    true
    (默认值为
    false
    )。相机堆叠:仅
    CameraRenderType.Base
    相机(或堆叠中的最后一个
    Overlay
    相机)应启用后期处理。同时需验证渲染器的PostProcessData资源不为空——若为空,则后期处理通道不存在。
  4. Volume的游戏对象层包含在相机的Volume层遮罩中——
    volumeLayerMask
    默认仅包含0层“Default”。Volume的
    GameObject.layer
    必须被包含在内,否则相机会忽略该Volume。
  5. 存在已启用的Volume,且带有有效的Profile及至少一个覆盖项——
    Volume
    组件必须启用,拥有非空的
    profile
    (或
    sharedProfile
    ),且至少有一个
    VolumeComponent
    的属性设置了
    overrideState = true

Pre-Flight Check Snippet

预检检查代码片段

Run this to verify the setup programmatically:
csharp
// `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();
运行以下代码以程序化验证设置:
csharp
// `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 Setup

1. Volume设置

Effects are added as VolumeComponent overrides on a VolumeProfile (a
ScriptableObject
).
Global Volume (most common): GameObject with
Volume
component,
isGlobal = true
,
profile
assigned. Affects every camera whose
volumeLayerMask
includes the Volume's layer.
Local Volume (optional, but takes precedence): GameObject with trigger
Collider
+
Volume
component,
isGlobal = false
. Properties:
  • priority
    (float) — higher values override lower when volumes overlap.
  • blendDistance
    (float) — outer distance in world units to start blending from (0 = no blend, instant transition at collider boundary).
  • weight
    (float, 0–1) — scales the volume's overall influence.
效果以VolumeComponent覆盖项的形式添加到VolumeProfile(一种
ScriptableObject
)中。
全局Volume(最常用):带有
Volume
组件的游戏对象,
isGlobal = true
,已分配
profile
。影响所有
volumeLayerMask
包含该Volume所在层的相机。
局部Volume(可选,但优先级更高):带有碰撞触发器
Collider
+
Volume
组件的游戏对象,
isGlobal = false
。属性:
  • priority
    (浮点数)——当多个Volume重叠时,值越高优先级越高。
  • blendDistance
    (浮点数)——开始混合的世界单位外距离(0表示无混合,在碰撞器边界处即时切换)。
  • weight
    (浮点数,0–1)——缩放Volume的整体影响程度。

2. Post-Processing Effects

2. 后期处理效果

All effects are
VolumeComponent
subclasses added as overrides on a
VolumeProfile
via
profile.Add<T>()
. Check existence with
profile.Has<T>()
or
profile.TryGet<T>(out var t)
. Remove with
profile.Remove<T>()
.
Every property is a
VolumeParameter
. You must set
overrideState = true
before setting
value
, otherwise the Volume system ignores it.
When configuring a specific effect, load the full API reference:
  • references/effect-reference.md — All VolumeComponent properties by effect (Bloom, Tonemapping, ColorAdjustments, DepthOfField, Vignette, MotionBlur, FilmGrain, ChromaticAberration, SplitToning, LensDistortion, WhiteBalance, PaniniProjection, LiftGammaGain, ShadowsMidtonesHighlights, ColorCurves, ChannelMixer)
For code templates:
  • references/code-templates.md — Global Volume setup, camera post-processing, and profile modification templates
所有效果均为
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)
代码模板:
  • references/code-templates.md — 全局Volume设置、相机后期处理及配置文件修改模板

3. Anti-Hallucination Rules

3. 防幻觉规则

Required Usings

必需的Using指令

These apply when you write a
.cs
file into the project. A snippet passed to
eval
cannot carry them
— qualify the types instead (see "Passing C# to
eval
" above).
csharp
using UnityEngine.Rendering;           // Volume, VolumeProfile, VolumeComponent, VolumeParameter
using UnityEngine.Rendering.Universal;  // Bloom, Tonemapping, ColorAdjustments, UniversalRenderPipeline, etc.
这些指令适用于你写入项目的
.cs
文件。传递给
eval
的代码片段不能包含这些指令
——请改用类型限定(参见上方“向
eval
传递C#代码”部分)。
csharp
using UnityEngine.Rendering;           // Volume, VolumeProfile, VolumeComponent, VolumeParameter
using UnityEngine.Rendering.Universal;  // Bloom, Tonemapping, ColorAdjustments, UniversalRenderPipeline, etc.

Wrong → Correct API Mapping

错误→正确API映射

WRONGCORRECT
PostProcessVolume
Volume
(from
UnityEngine.Rendering
)
PostProcessLayer
UniversalAdditionalCameraData.renderPostProcessing
(bool)
UnityEngine.Rendering.PostProcessing
UnityEngine.Rendering.Universal
profile.GetSetting<T>()
profile.TryGet<T>(out var t)
(returns bool)
profile.AddSettings<T>()
profile.Add<T>()
(returns T; throws if already exists — check
profile.Has<T>()
first)
volume.sharedProfile
(to modify at runtime)
volume.profile
(auto-clones the asset into an instance)
VolumeManager.instance.stack.GetComponent<T>()
volume.profile.TryGet<T>(out var t)
错误用法正确用法
PostProcessVolume
Volume
(来自
UnityEngine.Rendering
PostProcessLayer
UniversalAdditionalCameraData.renderPostProcessing
(布尔值)
UnityEngine.Rendering.PostProcessing
UnityEngine.Rendering.Universal
profile.GetSetting<T>()
profile.TryGet<T>(out var t)
(返回布尔值)
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)

Key Facts

关键事实

  • overrideState = true
    is required on every
    VolumeParameter
    you set. The volume system skips parameters where
    overrideState
    is
    false
    . This is the #1 scripting mistake.
  • sharedProfile
    = returns the asset directly (edits persist to disk).
    profile
    = auto-clones into an instance if needed (safe for runtime edits). Check with
    volume.HasInstantiatedProfile()
    .
  • profile.Add<T>(bool overrides = false)
    — pass
    true
    to auto-enable
    overrideState
    on all parameters of the added component.
  • **
    overrideState = true
    **是设置每个
    VolumeParameter
    的必需条件。Volume系统会跳过
    overrideState
    false
    的参数。这是脚本编写中最常见的错误。
  • sharedProfile
    = 直接返回资源(修改会持久化到磁盘)。
    profile
    = 必要时自动克隆为实例(适合运行时修改)。可通过
    volume.HasInstantiatedProfile()
    检查。
  • profile.Add<T>(bool overrides = false)
    — 传递
    true
    可自动启用添加组件的所有参数的
    overrideState

4. Debugging Checklist

4. 调试清单

When post-processing isn't working, check in order:
  1. cam.TryGetComponent<UniversalAdditionalCameraData>(out var data)
    succeeds and
    data.renderPostProcessing
    is
    true
    ?
  2. Volume exists in scene with a non-null
    profile
    (or
    sharedProfile
    ) assigned?
  3. Overrides added via
    profile.Add<T>()
    AND
    overrideState = true
    on each property you set?
  4. Volume's
    GameObject.layer
    is included in camera's
    data.volumeLayerMask
    ? (Default mask is layer 0 "Default" only.)
  5. volume.isGlobal = true
    (for global), or camera is inside the Volume's trigger
    Collider
    (for local)?
  6. Camera
    data.renderType
    is
    CameraRenderType.Base
    , not
    Overlay
    ? (Overlay cameras composite onto the Base camera's output.)
  7. UniversalRenderPipeline.asset.supportsHDR
    is
    true
    ? Required for Bloom and Tonemapping.
  8. Viewing in Game view? Scene view has a separate post-processing toggle in its toolbar.
当后期处理无法正常工作时,请按以下顺序检查:
  1. cam.TryGetComponent<UniversalAdditionalCameraData>(out var data)
    是否成功,且
    data.renderPostProcessing
    是否为
    true
  2. 场景中是否存在已分配非空
    profile
    (或
    sharedProfile
    )的Volume?
  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和色调映射的必需条件。
  8. 是否在Game视图中查看?Scene视图的工具栏中有单独的后期处理开关。

5. Common Recipes

5. 常用配置方案

Format: Effect property=value. Bloom values are threshold/intensity/scatter.
Cinematic (Film): 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
Stylized/Vibrant: Tonemapping mode=Neutral, ColorAdjustments saturation=20 contrast=10, Bloom threshold=0.8 intensity=1.5 scatter=0.6, SplitToning highlights=warm shadows=cool
Horror/Dark: 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
Clean/Mobile: Tonemapping mode=Neutral, ColorAdjustments postExposure=0.2, Bloom threshold=1.0 intensity=0.3 (subtle). Avoid FilmGrain, MotionBlur, DepthOfField on mobile.
格式:效果 属性=值。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=暖色调 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. Final Confirmation

6. 最终确认

After setup, report to user:
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).
设置完成后,向用户报告:
后期处理设置完成
- Volume:[全局/局部],位于"[游戏对象名称]"
- 配置文件:[资源路径]
- 效果:[包含关键属性=值对的列表]
- 相机:[名称] — renderPostProcessing=true,volumeLayerMask包含第[N]层

请在Game视图中查看结果(而非Scene视图)。
可通过编辑 > 撤销(Ctrl+Z)撤销所有更改。