关于 unity-lighting-vfx
面向 Unity 开发者的灯光与视觉特效参考技能,涵盖照明、全局光照、探针及粒子系统。还提供 VFX Graph 用法、C# 控制模式和常见误区。
主要功能
- 01实时、烘焙与混合照明
- 02全局光照与环境反射
- 03Light Probe 与 APV
- 04粒子系统模块参考
- 05VFX Graph 基础与模式
- 06C# 特效控制示例
适用场景
- 01为静态与动态场景选择灯光模式
- 02为移动对象配置间接照明
- 03比较 Particle System 与 VFX Graph
- 04排查照明和特效性能问题
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ nice-wolf-studio/ unity-claude-skills --skill unity-lighting-vfx安装后在 Claude Code 中输入/unity-lighting-vfx确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/lighting-guide.mdparticle-system.mdvfx-graph.md详细介绍
Unity 光照与视觉效果
光照模式
Unity 提供三种光照模式,用于控制光照的计算方式。
实时光照
- 在运行时每帧计算光照
- 支持动态更改强度、颜色和位置
- 投射阴影的距离不超过阴影距离
- 默认仅提供直接光照(无反弹光)
- 运行时开销较高,尤其是在复杂场景或低端硬件上
- 适用于:动态对象、闪烁效果、移动光源
烘焙光照
- 在 Unity 编辑器中执行计算,并将光照数据保存到磁盘
- 运行时,Unity 会加载预先计算的数据,而不是动态计算
- 将直接光照和间接光照都烘焙到光照贴图中
- 使用光照探针存储移动对象所需的信息
- 运行时无法修改光照属性;不会照亮动态 GameObject
- 不提供镜面反射贡献
- 适用于:静态场景、复杂的间接光照、对性能要求较高的场景
混合光照
- 将烘焙间接光照与实时直接光照结合起来
- 具体行为取决于 Lighting 窗口中的 Lighting Mode 设置
- 投射实时阴影(不是烘焙的软阴影)
- 运行时可以更改属性(仅影响实时部分)
- 开销始终高于完全烘焙的光照
- 适用于:背景光照已烘焙,但需要动态阴影的场景
重要提示: 所有烘焙/混合模式都要求启用烘焙全局光照。如果未启用,混合光照和烘焙光照的行为会与实时光照相同。
光源类型
定向光
- 位于无限远处,沿一个方向发光
- 光线彼此平行,强度不会随距离衰减
- 模拟太阳/月亮;每个新场景默认都包含一个定向光
- 与程序化天空系统关联;旋转定向光可创建昼夜效果
点光源
- 位于一个点上,向所有方向均匀发光
- 强度遵循平方反比定律(随距离平方增加而衰减)
- 用于灯具、爆炸、局部照明
聚光灯
- 位于一个点上,以圆锥形发光
- 圆锥角度可调;光线边缘会逐渐变暗(半影)
- 角度越大,渐隐区域越大
- 用于手电筒、车头灯、探照灯
面光源
- 由矩形或圆盘定义;光线从表面均匀发出
- 遵循平方反比定律;产生柔和、细腻的明暗效果
- 仅用于烘焙——运行时不可用
- 用于路灯、逼真的室内照明
全局光照
全局光照(GI)用于模拟光线在表面之间反弹,从而产生逼真的间接光照。
烘焙 GI
- 使用 Progressive Lightmapper(CPU 或 GPU)将间接光照预先计算到光照贴图中
- 结果存储在光照贴图纹理和光照探针中
- 在 Lighting 窗口的 Bake 设置下进行配置
- GPU Progressive Lightmapper 支持配置图块大小,可缩短烘焙时间
环境光照
Lighting 窗口的 Environment 选项卡中提供三种环境光源:
- 天空盒:使用天空盒材质颜色,从不同角度提供环境光
- 渐变:分别设置天空、地平线和地面颜色,并平滑混合
- 颜色:在整个场景中提供均匀的环境光
强度乘数(0-8,默认值为 1)用于控制环境光亮度。
环境反射
- 来源:天空盒或自定义 Cubemap/RenderTexture
- 可配置分辨率、压缩和强度乘数
- Bounces 设置用于控制对象之间反射计算的迭代次数
光照探针与自适应探针体积
光照探针
- 在整个场景的空旷空间中捕捉光照信息
- 运行时,使用最近的探针对动态 GameObject 的间接光照进行近似计算
- 为移动对象提供间接反弹光,并支持 LOD 系统
- 必须使用 Light Probe Groups 手动放置
- 存储烘焙光照信息;同时适用于直接光照和间接光照
自适应探针体积(APV)
APV 是 URP 中用于替代手动放置光照探针的现代方案:
- 自动放置探针 —— 无需手动调整光照探针组的位置
- 逐像素光照 —— 与逐对象方案相比,质量更出色
- 场景烘焙 —— 使用烘焙集同时烘焙多个场景
- 运行时调整 —— 使用光照方案和天空遮挡实现动态变化
- 支持大型世界 —— 为广阔的开放世界环境提供流式加载数据
- 数据灵活性 —— 可从 AssetBundles 或 Addressables 加载
- 可配置探针密度和体积大小,并提供可视化工具
反射探针
将周围环境的球形视图捕获为立方体贴图,用于反射材质。
类型
| 类型 | 描述 |
|---|---|
| 烘焙 | 仅捕获静态 GameObject;性能最佳 |
| 自定义 | 使用自定义纹理捕获动态对象 |
| 实时 | 在游戏过程中更新;可配置刷新模式 |
主要属性
- 重要性:多个探针重叠时的渲染优先级
- 强度:着色器计算中的纹理亮度
- 盒体投影:为室内场景启用投影映射(需要 URP 配置)
- 盒体大小/偏移:决定反射贡献的世界空间包围盒
- 混合距离:延迟探针的混合距离
实时选项
- 刷新模式:唤醒时、每帧或通过脚本
- 时间分片:一次渲染所有面、单独渲染各面、不进行时间分片
粒子系统与 VFX Graph
| 功能 | 粒子系统 | VFX Graph |
|---|---|---|
| 模拟 | 基于 CPU | 基于 GPU |
| 粒子数量 | 数千 | 数百万 |
| 渲染管线 | 所有管线 | 仅限 URP/HDRP |
| 创建方式 | Inspector 模块 | 基于节点的图形编辑器 |
| 物理效果 | 内置碰撞 | 自定义碰撞块 |
| 脚本编写 | 完整的 C# API | 基于事件的 C# API |
| 子发射器 | 原生支持 | GPU 事件上下文 |
| 最适合 | 小型/中型效果、移动平台 | 大规模效果、高端平台 |
选择指南:
- 目标平台为移动设备、效果简单、需要完全通过 CPU 端脚本控制,或目标为内置渲染管线时,请使用 粒子系统
- 需要海量粒子、GPU 驱动的模拟、复杂的基于节点的创作,或面向使用 URP/HDRP 的高端平台时,请使用 VFX Graph
粒子系统模块
| 模块 | 用途 |
|---|---|
| Main | 初始状态:生命周期、速度、大小、重力、模拟空间 |
| Emission | 粒子发射的速率和时机 |
| Shape | 发射体积/表面和起始速度方向 |
| Velocity over Lifetime | 根据粒子年龄修改运动 |
| Noise | 生成有机、混乱运动的湍流 |
| Limit Velocity over Lifetime | 实现自然减速 |
| Force over Lifetime | 模拟物理力 |
| Inherit Velocity | 子发射器粒子匹配父粒子的速度 |
| Lifetime by Emitter Speed | 根据发射器速度调整生命周期 |
| Color over Lifetime / by Speed | 根据年龄或速度改变颜色 |
| Size over Lifetime / by Speed | 根据时间或速度改变尺寸 |
| Rotation over Lifetime / by Speed | 改变方向 |
| Collision | 粒子与场景几何体碰撞 |
| Triggers | 将粒子指定为碰撞触发器 |
| Sub Emitters | 可发射其他粒子的粒子 |
| Texture Sheet Animation | 纹理网格动画帧 |
| Trails | 渲染运动轨迹 |
| Lights | 在粒子上生成实时光照 |
| External Forces | 风区和力场 |
| Renderer | 图像/网格变换、着色、过度绘制 |
| Custom Data | 为粒子附加自定义数据 |
VFX Graph 基础
系统
- 生成系统:由单个生成上下文管理发射
- 粒子系统:初始化 -> 更新 -> 输出的连续流程
- 网格输出系统:单个网格输出上下文
Context
- Spawn:执行每个帧以计算生成数量。状态:Running、Idle、Waiting。可配置循环时长、计数和延迟
- Initialize:在粒子诞生时运行,设置初始状态。为新生成的粒子处理 Blocks。可配置边界和容量
- Update:每帧处理所有存活粒子。自动执行:位置积分、旋转积分、老化和回收
- Output:渲染粒子(Quad、Mesh 等)。没有输出端口。可自定义渲染 Blocks
图形元素
- Blocks:Context 中可堆叠的节点;每个节点处理一项操作;按从上到下的顺序执行
- Operators:低级属性工作流节点,连接到 Block/Context 端口
- Properties:可通过属性工作流连接
- Settings:每个 Context 中可编辑但不可连接的值
GPU 事件
实验性功能,由 GPU 计算事件(普通事件由 CPU 计算)。无法使用 Blocks 自定义。
常见模式(C#)
创建并配置灯光
using UnityEngine;
public class LightSetup : MonoBehaviour
{
void Start()
{
GameObject lightObj = new GameObject("Dynamic Light");
Light light = lightObj.AddComponent<Light>();
light.type = LightType.Point;
light.color = Color.yellow;
light.intensity = 2.0f;
light.range = 15f;
light.shadows = LightShadows.Soft;
light.shadowResolution = UnityEngine.Rendering.LightShadowResolution.Medium;
}
}
创建实时反射探针
using UnityEngine;
using UnityEngine.Rendering;
public class ProbeSetup : MonoBehaviour
{
void Start()
{
GameObject probeObj = new GameObject("Realtime Reflection Probe");
ReflectionProbe probe = probeObj.AddComponent<ReflectionProbe>();
probe.size = new Vector3(10, 10, 10);
probe.mode = ReflectionProbeMode.Realtime;
probe.refreshMode = ReflectionProbeRefreshMode.EveryFrame;
probe.resolution = 256;
probe.hdr = true;
}
}
在运行时控制粒子系统
using UnityEngine;
public class ParticleController : MonoBehaviour
{
ParticleSystem ps;
void Start()
{
ps = GetComponent<ParticleSystem>();
// Modify emission rate -- cache module in local variable first
var emission = ps.emission;
emission.rateOverTimeMultiplier = 50f;
// Modify main module
var main = ps.main;
main.startLifetime = 3f;
main.startSpeed = 5f;
main.simulationSpace = ParticleSystemSimulationSpace.World;
}
void OnTriggerEnter(Collider other)
{
// Burst emit particles
ps.Emit(100);
}
void OnDisable()
{
ps.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
}
}
VFX Graph 运行时控制
using UnityEngine;
using UnityEngine.VFX;
public class VFXController : MonoBehaviour
{
VisualEffect vfx;
VFXEventAttribute eventAttr;
void Start()
{
vfx = GetComponent<VisualEffect>();
eventAttr = vfx.CreateVFXEventAttribute();
// Set exposed properties
vfx.SetFloat("SpawnRate", 100f);
vfx.SetVector3("Direction", Vector3.up);
vfx.playRate = 1.5f;
}
void OnTriggerEnter(Collider other)
{
// Send custom event with attributes
eventAttr.SetVector3("position", other.transform.position);
vfx.SendEvent("OnHit", eventAttr);
}
public void StopEffect()
{
vfx.Stop();
}
}
按需刷新反射探针
using UnityEngine;
public class ProbeRefresher : MonoBehaviour
{
ReflectionProbe probe;
void Start()
{
probe = GetComponent<ReflectionProbe>();
probe.refreshMode = UnityEngine.Rendering.ReflectionProbeRefreshMode.ViaScripting;
}
public void RefreshReflections()
{
probe.RenderProbe();
}
public bool IsReady()
{
return probe.IsFinishedRendering(probe.RenderProbe());
}
}
反模式
灯光反模式
- 实时灯光过多:每盏实时灯光都会增加逐帧开销。静态灯光请使用 Baked 或 Mixed
- 忘记启用烘焙全局光照:未启用此功能时,Mixed/Baked 灯光会静默回退到 Realtime
- 反射探针重叠但未设置 Importance 值:会导致闪烁;务必设置 Importance 以确定优先级
- 使用 Area Lights 并期待其在运行时生效:Area Lights 仅用于烘焙;运行时不会产生光照
- 忽略 Indirect Multiplier:保留默认值可能导致反弹光过亮或过暗;请针对每盏灯光进行调整
- 未正确设置 Shadow Bias:值过低会导致自阴影伪影(shadow acne);值过高会导致阴影悬浮(阴影与物体分离)
- 在大型场景中手动放置 Light Probe:在 URP 中改用 Adaptive Probe Volumes(APV),以实现自动化的逐像素高质量效果
粒子系统反模式
- 未缓存模块引用:每次访问模块结构体的属性都会立即写入原生代码;请缓存模块变量
- 对附着效果使用 World 模拟空间:粒子会逐渐偏离移动的父对象;附着 FX 请使用 Local 空间
- CPU 上的粒子数量过多:Particle System 受 CPU 限制;粒子数超过 10K 时,请考虑使用 VFX Graph
- 忘记调用 Stop/Clear:即使不可见,未清理的粒子系统仍会消耗 CPU
VFX Graph 反模式
- 在移动设备上使用 VFX Graph 实现简单效果:GPU 开销以及对 URP/HDRP 的要求,使其对于简单的移动端效果而言过于复杂
- 未在 Initialize 中设置 Capacity:默认容量可能分配过多或过少的 GPU 内存
- 忽略 Bounds:边界设置不正确会导致可见效果被剔除;务必在 Initialize Context 中配置边界
- 每帧发送事件但不进行节流:SendEvent 会产生 CPU-GPU 同步开销;请批量处理事件派发或进行节流
关键 API 快速参考
Light(UnityEngine.Light)
| 成员 | 类型 | 描述 |
|---|---|---|
type | 属性 | LightType(Directional、Point、Spot、Area) |
color | 属性 | 发出的光线颜色 |
intensity | 属性 | 亮度乘数 |
range | 属性 | 最大距离(Point/Spot) |
spotAngle / innerSpotAngle | 属性 | 锥形光束的外角和内角 |
shadows | 属性 | LightShadows(None、Hard、Soft) |
shadowResolution | 属性 | 阴影贴图质量 |
shadowBias / shadowNormalBias | 属性 | 减少阴影伪影 |
bounceIntensity | 属性 | GI 反弹强度 |
cookie | 属性 | 投射的纹理遮罩 |
cullingMask | 属性 | 基于图层的筛选 |
colorTemperature | 属性 | 以开尔文为单位的 CCT |
lightmapBakeType | 属性 | 烘焙配置 |
bakingOutput | 属性 | 上次烘焙的贡献详情 |
AddCommandBuffer() | 方法 | 在指定时机执行 GPU 命令 |
ParticleSystem(UnityEngine.ParticleSystem)
| 成员 | 类型 | 描述 |
|---|---|---|
main / emission / shape | 属性 | 模块访问结构体 |
particleCount | 属性 | 当前活动粒子数 |
isPlaying / isPaused / isStopped | 属性 | 播放状态 |
Play() / Pause() / Stop() | 方法 | 播放控制 |
Emit(count) | 方法 | 立即生成粒子 |
Simulate(time) | 方法 | 快进模拟 |
GetParticles() / SetParticles() | 方法 | 直接访问粒子数据 |
Clear() | 方法 | 移除所有粒子 |
TriggerSubEmitter() | 方法 | 激活子发射器 |
VisualEffect(UnityEngine.VFX.VisualEffect)
| 成员 | 类型 | 描述 |
|---|---|---|
visualEffectAsset | 属性 | 指定或更改效果图 |
playRate | 属性 | 模拟速度 |
aliveParticleCount | 属性 | 活动粒子数 |
Play() / Stop() / Reinit() | 方法 | 播放控制 |
SendEvent(name, attr) | 方法 | 触发效果图事件 |
CreateVFXEventAttribute() | 方法 | 创建事件载荷 |
SetFloat() / SetVector3() / etc. | 方法 | 设置公开属性 |
GetFloat() / GetVector3() / etc. | 方法 | 读取公开属性 |
HasFloat() / HasVector3() / etc. | 方法 | 检查属性是否存在 |
ResetOverride(property) | 方法 | 恢复原始值 |
ReflectionProbe(UnityEngine.ReflectionProbe)
| 成员 | 类型 | 描述 |
|---|---|---|
mode | 属性 | Baked/Custom/Realtime |
size / center | 属性 | 边界框配置 |
intensity / importance | 属性 | 亮度和优先级 |
boxProjection | 属性 | 启用盒形投影 |
refreshMode / timeSlicingMode | 属性 | 实时更新配置 |
RenderProbe() | 方法 | 强制刷新立方体贴图 |
IsFinishedRendering() | 方法 | 检查分时渲染是否完成 |
BlendCubemap() | 方法 | 混合两个立方体贴图 |
相关技能
unity-graphics-- 渲染管线(URP/HDRP/内置)、着色器、材质、摄像机unity-2d-- 2D 光照(URP 2D Renderer)、精灵渲染unity-platforms-- 特定平台的光照质量等级、移动端优化
Additional Resources
评论
支持 Markdown