UE5 动态天气系统:雨、雪、雾的 Niagara 实现方案
上周有位学员在群里发了一个问题:“老师,我按教程做了个下雨特效,但粒子从天上掉下来时总是穿模到建筑内部,而且雨滴没有碰撞效果,看起来像玻璃碎片。怎么让雨滴碰到地面反弹或者消失?”这个问题其实很典型——很多刚接触 Niagara 的人会把天气特效简单理解为“粒子发射”,忽略了物理交互和视觉真实感的细节。今天我们就从雨、雪、雾三种天气入手,用 Niagara 实现一套可动态切换的天气系统,重点解决粒子碰撞、密度控制、以及雾效的深度融合问题。
一、雨滴的物理碰撞与视觉优化
1.1 基础雨滴粒子设置
首先在 UE5.3 中新建一个 `Niagara System`,选择“来自模板”并选 `Empty`。在 `Emitter Properties` 中设置:
- Life Cycle:`Emitter Duration` 设为 0(无限循环),`Loop Behavior` 选 `Infinite`
粒子形状用 `Sprite Renderer`,材质选择 `M_RainDrop`(需提前创建,使用半透明 Blend Mode,纹理为水滴状渐变图)。��键参数:
1.2 碰撞系统的实现
要让雨滴碰到地面消失或反弹,需要启用 `Collision` 模块。在 Niagara 编辑器中:
1. 添加 `Collision` 模块到 `Particle Update` 阶段
2. 设置 `Collision Type` 为 `World Collision`(注意:UE5 中 `World Collision` 会检测静态网格体和地形,但不检测动态物体)
3. `Collision Mode` 选 `Surface Only`,避免粒子之间互相碰撞
4. `Friction` 设为 0.3,`Bounce Restitution` 设为 0.1(让雨滴几乎不反弹,直接消失)
5. 勾选 `Use Velocity for Collision`,让粒子速度影响碰撞方向
关键技巧:如果发现粒子穿模到建筑内部,检查 `Collision Channel` 是否包含 `WorldStatic`。在项目设置中,`Collision` → `Preset` 里确保 `WorldStatic` 对 `Particle` 通道是 `Block`。另外,`Collision Radius` 设为 0.1 可减少粒子在边缘的抖动。
1.3 视觉增强:风与动态模糊
雨滴需要随风飘动,在 `Particle Update` 中添加 `Force` 模块:
为了让雨滴有动态模糊效果,在 `Sprite Renderer` 的 `Material Parameters` 中,将 `Particle Direction` 传入材质的 `UV` 偏移量。材质蓝图里用 `Particle Relative Time` 乘以速度向量,让纹理沿粒子运动方向拉伸。
二、雪的堆积与密度控制
2.1 粒子发射参数优化
雪的粒子比雨滴更轻、更慢。新建一个 Niagara System,参数调整如下:
2.2 堆积效果的实现
雪落在物体表面需要形成堆积层。这里用 `Collision` + `Particle ID` 实现:
1. 在 `Emitter Update` 中添加 `Spawn Per Unit`,设置 `Spawn Rate` 为 0(禁用自动生成),改用 `Collision` 事件触发生成堆积粒子
2. 添加 `Event Handler`,监听 `Collision Event`,当粒子碰撞时,在碰撞位置生成一个���的 `Snow Pile` 粒子
3. `Snow Pile` 粒子的 `Life Time` 设为 30-60 秒,`Size` 逐渐增大(用 `Particle Age` 控制缩放),模拟积雪
注意:堆积粒子需要禁用 `Collision`,否则会继续触发事件导致无限循环。另外,`Snow Pile` 粒子的 `Sprite Renderer` 用 `Unlit` 材质,颜色设为 `(0.9,0.95,1.0)`,透明度 0.8。
2.3 密度控制脚本
为了在不同区域控制雪的密度,用 `User Parameters` 暴露 `Snow Density`(Float,0-1)。在 `Spawn` 阶段用 `Spawn Burst Instantaneous`,数量乘以 `Snow Density`。另外,在 `Particle Update` 中添加 `Scale Color` 模块,根据密度调整透明度:
Color = Lerp(LinearColor(0,0,0,0), LinearColor(1,1,1,1), Snow Density)
这样密度为 0 时雪完全透明,达到“无雪”效果。
三、雾效的深度与动态控制
3.1 基于高度场的雾粒子
雾不能用传统 Sprite 粒子,因为需要体积感。推荐用 `Mesh Renderer` 配合球体网格:
1. 在 Niagara 中创建 `Emitter`,`Renderer` 选 `Mesh Renderer`
2. `Mesh` 选择 `Sphere`(引擎自带),`Scale` 设为 `Uniform(100,300)` cm
3. `Material` 用 `M_FogVolume`,材质设置为 `Unlit`,`Blend Mode` 为 `Additive`
4. 粒子数量:100-300 个即可,太多会卡
关键参数:
3.2 密度与高度的动态映射
雾的密度应该随高度变化:地面浓,高空稀。在 `Particle Update` 中添加 `Scale Color` 模块,用 `Particle Position Z` 计算:
Height = Particle Position Z - Ground Z
Density = 1 - saturate(Height / Max Height)
Color = LinearColor(0.8, 0.85, 0.9, Density * 0.5)
`Max Height` 设为 500 cm(雾顶高度),`Ground Z` 用 `User Parameter` 暴露,方便调整。
3.3 与场景光照的融合
雾的颜色需要匹配环境光。在 `User Parameters` 中添加 `Fog Color`(LinearColor),从场景的 `Directional Light` 颜色采样。在材质中,用 `Fog Color` 乘以 `Particle Color`,实现动态调色。
进阶技巧:用 `Noise` 模块让雾粒子位置产生随机扰动,模拟风的影响。在 `Particle Update` 中添加 `Noise`,`Noise Mode` 选 `Position`,`Frequency` 设为 0.1,`Amplitude` 设为 50 cm,让雾产生流动感。
四、系统集成与动态切换
4.1 天气状态蓝图控制
在蓝图中创建一个 `Weather Manager` Actor,包含三个 Niagara 组件(分别对应雨、雪、雾)。暴露三个布尔变量:`bRain`、`bSnow`、`bFog`,在 `Tick` 中根据状态启用/禁用组件:
// 伪代码
if (bRain) RainComponent->Activate();
else RainComponent->Deactivate();
注意:`Activate` 会重置粒子系统,建议用 `SetVisibility` 控制显示/隐藏,避免性能开销。
4.2 过渡动画
从雨切换到雪时,需要平滑过渡。在 Niagara 中,用 `User Parameters` 暴露 `Transition Time`(Float),在 `Spawn` 阶段用 `Lerp` 将粒子数量从当前值过渡到目标值。例如:
Spawn Rate = Lerp(CurrentRate, TargetRate, Transition Time / Total Transition Duration)
`Total Transition Duration` 设为 2-3 秒,让天气变化自然。
五、性能优化建议
1. LOD 控制:对远处的粒子降低 `Spawn Rate` 和 `Size`。在 Niagara 中,用 `Camera Distance` 条件判断,距离 > 5000 cm 时粒子数量减半。
2. 粒子池复用:用 `Particle Pool` 模块,避免频繁分配/释放内存。
3. 材质复杂度:雨滴和雪的材质用 `Simple` 材质域,雾的材质用 `Surface`,避免使用 `World Position Offset` 等重计算。
总结与进阶建议
这套天气系统已经解决了粒子碰撞、堆积和雾效体积感的核心问题。但如果你想做更真实的效果,可以进一步探索:
建议学员先实现基础版本,再逐步添加细节。如果遇到粒子性能问题,优先检查 `Spawn Rate` 和 `Collision` 的 `Trace Channel` 设置。
常见问题 FAQ
Q1:粒子碰撞时总是穿透地面,怎么解决?
A:检查 `Collision Channel` 是否包含 `WorldStatic`,并在项目设置中确认 `Particle` 通道对 `WorldStatic` 是 `Block`。另外,`Collision Radius` 设置过小(<0.05)会导致穿透,建议设为 0.1-0.2。
Q2:雪的堆积粒子无限生成,导致场景卡死?
A:堆积粒子必须禁用 `Collision`,否则会反复触发碰撞事件。在 `Snow Pile` 的 `Emitter Properties` 中,将 `Collision` 模块移除或设为 `Disabled`。
Q3:雾的粒子看起来像一团团球体,没有体积感?
A:尝试用 `Noise` 模块扰动粒子位置,同时将 `Mesh Scale` 的随机范围扩大(如 100-500 cm)。材质中增加 `Opacity` 的随机性,让粒子边缘淡出。
Q4:天气切换时有明显的粒子闪烁?
A:这���由于 `Activate`/`Deactivate` 重置了粒子系统。改用 `SetVisibility` 控制组件显示,并在 `User Parameters` 中用 `Lerp` 过渡粒子数量。
Q5:雨滴在高速移动时出现撕裂?
A:在 `Sprite Renderer` 中启用 `Sort Priority`,设置为 `-10`(让雨滴优先渲染)。同时增大 `Sub Image` 的 `Blend` 值,或改用 `Triangle` 网格代替 Sprite。
—
如果你在实现过程中遇到具体问题,欢迎在评论区留言,我会挑选典型问题在后续文章中详细解答。

评论(0)