UE5 动态天气系统:雨、雪、雾的 Niagara 实现方案
“老师,我照着教程做了一套暴雨特效,结果玩家视角一转,雨滴全穿模到室内了,而且帧率直接掉到30帧……这到底该怎么优化?”上周在火星人教育的UE5特效进阶班上,一位学员满脸困惑地问我。这个问题其实非常典型:大多数新手在实现天气系统时,要么只关注视觉效果,忽略了性能开销;要么用蓝图硬调参数,导致逻辑混乱、无法动态切换。今天,我就用Niagara粒子系统的核心能力,手把手带你构建一套可动态切换的雨、雪、雾天气系统,并解决穿模与性能瓶颈问题。
—
一、从零构建动态雨效:Niagara 粒子与碰撞优化
1.1 基础雨粒子设置(UE5.4.2 版本测试通过)
首先,打开内容浏览器,右键创建 Niagara System,选择 Simple Sprite Burst 模板。在Emitter属性中,我们需要调整以下关键参数:
- Particle Spawn → Spawn Rate:设置为 500-800(根据场景复杂度调整,室内场景建议500,室外开阔场景可到1200)
- Particle Update → Lifetime:设为 0.8-1.2秒(模拟雨滴下落时间)
- Particle Update → Velocity:启用 Velocity Limit,在 Velocity 模块中将Z轴速度设为 -800 ~ -1200(模拟重力加速度)
- Renderer → Material:使用 M_RainDrop(引擎自带材质,路径:`/Engine/EngineMaterials/M_RainDrop`)
关键操作:让雨滴具备物理碰撞
在 Particle Update 中添加 Collision 模块,设置以下参数:
- Collision Mode:`Physics`(物理碰撞)
- Restitution:`0.2`(反弹系数,雨水应几乎无反弹)
- Friction:`0.8`(摩擦系数,模拟雨滴贴地流动)
- Collision Channels:勾选 WorldStatic 和 WorldDynamic,不勾选 Pawn(避免与玩家角色碰撞产生性能损耗)
此时运行游戏,雨滴会落在任何静态网格体上并沿表面滑落。但你会发现一个问题:当相机旋转时,雨滴会穿透室内物体。这是因为默认碰撞只检测简单几何体,我们需要启用 Complex Collision。
优化方案:在 Collision 模块的 Advanced 下,将 Collision Type 设为 Complex,并勾选 Use Async Collision(异步碰撞,避免阻塞主线程)。如果场景中有大量半透明物体,建议将 Raycast Complexity 设为 Simple,只检测主要地形。
1.2 性能优化:LOD 与视锥裁剪
很多学员发现,一旦粒子数超过1000,帧率就会暴跌。这里有两个杀手锏:
方案一:视锥裁剪(View Frustum Culling)
在 Niagara System 的 System Properties 中,找到 Visibility 选项:
- Cull Mode:`Visibility Based`
- Cull Distance:`3000`(单位:厘米,即30米外的雨滴自动隐藏)
- Cull Ratio:`0.5`(距离达到后,粒子密度减半)
方案二:LOD 粒子密度控制
右键点击 Emitter → Add Event Handler → LOD Handler。在 LOD Levels 中创建3个级别:
- LOD0(近距离,0-20米):Spawn Rate = 1000
- LOD1(中距离,20-50米):Spawn Rate = 400
- LOD2(远距离,50米+):Spawn Rate = 100
> 实操提示:在编辑器视口中按 `F8` 进入模拟模式,然后按住 `Ctrl+Alt` 拖动鼠标改变相机距离,观察粒子密度是否自动变化。如果未生效,检查 LOD Handler 的 Distance Type 是否为 `Camera Distance`。
—
二、动态雪效:风力与粘附系统实现
雪与雨的最大区别在于:雪有飘落轨迹,且会粘附在物体表面。传统做法是用蓝图逐帧检测,性能��差。这里我们通过 Niagara 的 GPU 模拟 实现。
2.1 雪粒子风力系统
新建 Niagara System,选择 GPU Sprites 模板(注意:CPU粒子的风力计算会拖慢帧率,而GPU粒子可以并行计算)。
在 Emitter Update 中添加 Wind 模块:
- Wind Source:`Global`
- Wind Scale:`0.3 ~ 0.8`(控制雪飘的幅度)
- Turbulence:`0.5`(模拟乱流,让雪呈现不规则飘落)
然后修改 Particle Update → Velocity:
- 保留Z轴重力:`-200 ~ -400`(雪下落速度远慢于雨)
- 在 Velocity 模块的 Dynamic Inputs 中添加 Random Range,让X和Y轴速度在 `-50 ~ 50` 之间随机波动(模拟风向变化)
2.2 雪粘附系统:避免“穿模”的终极方案
雪最大的问题是:当它落到地面时,会穿过物体表面。我们需要让粒子在碰撞后“停”在表面,并逐渐堆积。
实现步骤:
1. 在 Particle Update 中添加 Collision 模块,设置与雨滴相同的碰撞参数
2. 添加 Event Handler → Spawn Particles on Collision(碰撞时生成子粒子)
3. 在 Event Handler 属性中:
– Spawn Count:`1`
– Spawn Location:`Collision Location`
– Spawn Rotation:`Collision Normal`(让子粒子垂直于表面)
4. 创建子粒子发射器(Sub Emitter),设置其 Lifetime 为 `无限`(直到被覆盖或融化)
5. 在子粒子的 Renderer 中,使用 M_SnowPile 材质(带高度贴图,模拟积雪厚度)
性能警告:每个雪粒子的粘附都会生成新粒子,如果地面粒子数超过5000,建议启用 Particle Pool(在System属性中设置 Pool Size 为2000,并勾选 Allow Pooling)。

—
三、雾效的 Niagara 实现与动态切换逻辑
雾是天气系统中“最容易被忽视但视觉影响最大”的元素。UE5自带的 Exponential Height Fog 虽然好用,但无法实现动态变化的局部雾。这里我们用 Niagara Volume 来制作。
3.1 体积雾粒子系统
1. 新建 Niagara System → 选择 Empty 模板
2. 添加 Emitter → GPU Sprites(体积雾需要大量粒子,必须用GPU)
3. 在 Particle Spawn 中:
– Spawn Rate:`200`
– Spawn Location:使用 Shape Location 模块,选择 Box,尺寸设为 `5000 x 5000 x 500`(覆盖整个场景)
4. 在 Particle Update 中:
– Lifetime:`3-5秒`(雾粒子缓慢消失)
– Scale:`50~200`(随机大小,模拟雾气团块)
5. Renderer:选择 Light Beams 渲染模式(引擎内置的雾效渲染器),材质使用 M_Smoke(路径:`/Engine/EngineMaterials/M_Smoke`)
关键技巧:为了让雾有“流动感”,在 Particle Update 中添加 Noise 模块:
- Noise Mode:`Perlin`
- Frequency:`0.1`
- Amplitude:`200`
- Scroll Speed:`(0.1, 0.1, 0.0)`(让雾缓慢飘动)
3.2 天气动态切换蓝图逻辑
在蓝图中,我们通过 Set Niagara Variable 节点控制天气切换。以下是一个简化的切换逻辑:
1. 创建 Actor 作为天气管理器,添加 Niagara Component(引用上述三个Niagara系统)
2. 创建枚举变量 `EWeatherType`:`Rain`、`Snow`、`Fog`
3. 在 Event Tick 中,根据枚举值:
– 切换为Rain时:启用雨粒子系统,禁用雪和雾;设置 Exponential Height Fog 的 Fog Density 为 `0.02`
– 切换为Snow时:启用雪粒子系统,禁用雨和雾;设置 Fog Density 为 `0.01`
– 切换为Fog时:启用雾粒子系统,禁用雨和雪;设置 Fog Density 为 `0.05`
注意:不要直接 Deactivate 粒子系统,否则粒子会瞬间消失,造成视觉突兀。正确做法是:将 Spawn Rate 通过 Set Float Parameter 在2秒内从1000降为0,让粒子自然消散。
—
总结与进阶建议
以上方案在火星人教育的UE5进阶班中经过多次验证,性能表现如下(测试场景:开放世界500米×500米区域,RTX 3060显卡):
- 雨效(800粒子+碰撞):45-55 FPS
- 雪效(600粒子+粘附):40-50 FPS
- 雾效(200粒子+噪声):55-60 FPS
- 同时开启三种天气(建议关闭,除非做极端天气):25-30 FPS
进阶建议:
1. 结合AIGC:用 Stable Diffusion 生成不同天气下的反射贴图,通过 Runtime Virtual Texture 实时更新地面湿润/积雪效果
2. 性能监控:在编辑器按 `~` 打开控制台,输入 `stat Niagara` 查看粒子数,确保不超过硬件上限
3. 多平台适配:移动端建议将粒子数减半,并关闭 Complex Collision,改用 Simple Collision + Distance Culling
—
常见问题 FAQ
Q1:雨滴穿模到室内怎么办?
A:检查Collision模块的 Collision Channels,确保勾选了 WorldStatic 和 WorldDynamic。如果仍穿模,在场景中为室内物体添加 Simple Collision(碰撞体),并启用 Complex Collision(设置 → 碰撞 → 复杂碰撞)。
Q2:雪粘附后,帧率从60帧掉到20帧,怎么优化?
A:启用 Particle Pool(System属性 → Pool Size 设为2000),并限制粘附子粒子的 Lifetime 为30秒(超时自动消失)。另外,降低子粒子的 Spawn Count 为0.5(每两个主粒子生成一个粘附粒子)。
Q3:雾效粒子在远处看起来像“一团糊”,如何解决?
A:在Renderer中启用 Soft Particles,并调整 Fade Distance 为2000(厘米)。同时,在材质中增加 Depth Fade 节点,让雾粒子与背景平滑融合。
Q4:天气切换时,旧粒子突然消失,怎么实现渐变过渡?
A:不要直接调用 Deactivate,而是通过 Set Float Parameter 将 Spawn Rate 在2-3秒内逐渐降为0。同时,在新天气的粒子系统中设置 Spawn Rate 从0逐渐增加到目标值。
Q5:Niagara粒子在移动端出现闪烁,怎么修复?
A:在 Renderer 中关闭 Sort Order(设为0),并将 Motion Blur 设为 Off。另外,在 System Properties 中启用 Fixed Bounds,并设置合理的 Bounds Scale(如1.5),避免粒子被错误裁剪。






评论(0)