Niagara 流体模拟实战:水、火、烟的真实感制作技巧

上周有位学员在群里发来一段视频:他用Niagara做了个火焰喷射效果,但看起来像一堆僵硬的橙色方块在飘。这个问题很典型——很多新手掌握了粒子系统的基础操作,却卡在“真实感”这道坎上。流体模拟在UE5里其实有章可循,今天我们就从水、火、烟三个最常用的流体类型入手,拆解真实感制作的核心技巧。

在开始之前,确保你使用的是 Unreal Engine 5.3 或更高版本,Niagara系统在5.3后对GPU模拟做了大幅优化。项目设置中需开启 Support Compute SkincacheSupport Ray Tracing(可选,用于反射效果)。

一、火焰:从“色块”到“有生命的跃动”

学员那个火焰问题出在哪?仔细观察你会发现:真实的火焰有内焰(蓝色/白色)、外焰(橙红/黄色),而且会因气流产生卷曲和分裂。Niagara默认的粒子是刚性球体,必须用纹理采样+动态变形来模拟。

步骤1:创建基础火焰发射器

1. 右键Content Browser → FXNiagara System → 选择 Empty → 命名为 `FX_Fire`
2. 添加一个 GPU Emitter(火焰粒子数量通常上万,CPU吃不消)
3. 在 Emitter Properties 中设置:
Simulation Target: GPUComputeSim
Fixed Bounds: 勾选,设置Bounds为 `(200, 200, 300)` 避免粒子被裁剪

步骤2:核心参数配置

Particle Spawn 模块:

  • Lifetime: 设置范围为 `0.8-1.5` 秒(火焰粒子存活时间短才有闪烁感)
  • Sprite Size: 使用 Uniform Random,范围 `30-80` 单位
  • Color: 通过 Curve 控制颜色随生命周期变化——0时刻为白色(高温),0.3时刻为亮黄,0.7时刻为橙红,1时刻为暗红(将死)
  • Particle Update 模块:

  • Add Velocity: 在 Velocity 节点中,Z轴设为 `100-300` 的随机值(火焰向上),XY轴添加 Noise 节点(频率0.5,振幅30),模拟热空气扰动
  • Scale Color: 使用 Sample Curve 节点,将粒子年龄映射到颜色曲线
  • 步骤3:实现火焰的“卷曲”效果

    这是真实感的关键。在 Particle Update 中添加 Vortex Noise

  • Noise Strength: `50-150`
  • Noise Frequency: `0.3-0.6`
  • Vortex Strength: `0.2-0.5`
  • Turbulence: 勾选,强度设为 `20`
  • 此时粒子会像被气流拉扯一样产生螺旋运动。再添加 Curl Noise 节点(位置在 Noise 菜单下),强���设为 `10`,频率 `0.8`,你会发现火焰边缘出现细碎的卷曲——这是真实火焰的典型特征。

    火焰粒子卷曲效果

    步骤4:材质配合

    在火焰材质中(使用 Material DomainSurfaceBlend ModeAdditive):

  • 将粒子的 ColorOpacity 通过 Particle Color 节点接入
  • 使用 Texture CoordinatePivot 设为 `(0.5, 0.5)`,配合 Panner 节点沿Y轴滚动,让火焰纹理动态流动
  • 添加 Depth Fade 节点,让火焰边缘半透明,避免硬边
  • 调试技巧:在Niagara编辑器按 `Ctrl+Shift+逗号` 打开 Debug Draw,勾选 Particle BoundsVelocity,能看到粒子运动轨迹是否自然。

    二、水:从“水滴”到“流体表面”

    水模拟比火焰复杂,因为涉及表面张力和碰撞。我们不做全物理模拟(那是Houdini的领域),而是用粒子网格化技巧模拟水流表面。

    案例:瀑布效果

    1. 创建新发射器 `FX_Waterfall`,同样用GPU模拟
    2. Spawn Rate: `5000-10000` 粒子/秒
    3. Initial Velocity: Z轴 `-500`(向下),XY轴添加 Random 范围 `-50到50`(飞溅扩散)

    关键技巧1:粒子大小随速度变化

    Particle Update 中:

  • 获取 Particle Velocity 的长度
  • Map Range 节点将速度映射到 `10-60` 的范围
  • 输出到 Sprite Size 的 X 和 Y 轴
  • 这样水下落越快,粒子拉得越长(像水滴被重力拉伸),落在水面时会变扁(速度降低)。

    关键技巧2:模拟表面张力

    添加 Custom HLSL 模块(位置在 Particle Update 的 Add Module 中):

    // 计算粒子与邻居的间距
    float Dist = length(NeighborPosition - Position);
    // 如果间距小于阈值,施加斥力防止穿透
    if(Dist < 20.0) {
        float Force = (20.0 - Dist) * 0.5;
        Velocity += normalize(Position - NeighborPosition) * Force;
    }
    

    这个脚本需要配合 Grid 3D 缓存(在 Niagara 的 Simulation Stage 中启用),让粒子在网格内互相感知。网格分辨率设为 `64x64x64`,太小会漏掉碰撞,太大会消耗性能。

    步骤3:渲染为流体表面

    单纯粒子看起来像喷泉,要变成水流需要 Mesh Particles

  • Renderer 中改为 Mesh Renderer,选择 Sphere 网格(默认)
  • 但更好的方法是使用 Custom RendererFluid Surface(UE5.3新增)
  • 设置 Surface Tension: `0.8`(控制表面光滑度)
  • Vortex Confinement: `0.3`(增加水流旋转细节)
  • 瀑布流体表面效果

    此时你会看到粒子融合成连续的水流表面,边缘有飞溅的水花——这得益于Fluid Surface渲染器自动对粒子进行Marching Cubes网格化。

    性能优化

  • 粒子数量超过20000时,启用 Fixed Time Step(在Emitter Properties中),设为 `0.016`(60fps对应)
  • Particle Spawn 中限制 Max Particles 为 `50000`,超出部分用 Kill Particles 模块处理
  • 三、烟:从“团块”到“消散的层次感”

    烟最难的是“消散感”——它不像火那样有明确边界,而是逐渐稀释到透明。很多学员直接用Opacity渐变,结果看起来像雾而不是烟。

    步骤1:基础烟粒子

  • 创建 `FX_Smoke`,使用GPU模拟
  • Lifetime: `3-6` 秒(烟比火消散慢)
  • Sprite Size: `50-200` 单位,随时间逐渐增大(烟会扩散)
  • Initial Velocity: 缓慢上升 `20-80` 单位/秒,XY轴噪声扰动
  • 步骤2:实现“层次感”的核心——多层噪声

    Particle Update 中:
    1. 添加 Scale Color 模块,用曲线控制Opacity:0时刻为0.8,0.5时刻为0.5,1时刻为0(完全消散)
    2. 添加 Scale Size 模块,用曲线让大小随时间指数增长
    3. 最关键:在材质中叠加两层噪声纹理

    材质做法:

  • 第一层:Texture Sample 使用 `T_PerlinNoise_256`(引擎自带),UV滚动速度 `(0.1, 0.05)`
  • 第二层:Texture Sample 使用 `T_VoronoiNoise_256`,UV滚动速度 `(0.05, -0.02)`
  • 两层相乘后,乘以 Particle Color 的Alpha通道
  • 这样烟的内部会有“絮状”结构,边缘因为两层噪声叠加产生不规则消散——就像真实烟雾被气流撕扯。

    步骤3:模拟热力上升

    烟通常伴随热源(比如火焰),所以需要模拟热空气上升:

  • 添加 Acceleration Force 模块,Z轴设为 `50-100`
  • 添加 Drag 模块,设为 `0.1-0.3`(空气阻力越大,烟越“厚重”)
  • Particle Update 中添加 Vortex Noise,强度 `30`,频率 `0.2`
  • 烟雾多层噪声效果

    步骤4:光晕与体积感

    烟在光照下会有明显的体积感。在材质中:

  • 使用 Custom Lighting 模式,接入 Simple Forward Lighting 节点
  • 添加 Subsurface Color 节点,颜色设为浅灰蓝,强度 `0.3`(模拟光线穿过薄烟)
  • 开启 Two Sided 选项(默认关闭),让烟从背面看也有厚度
  • 如果项目允许,可以配合 Volumetric Fog(在Post Process Volume中启用),设置 Fog Density 为 `0.02`,Fog Albedo 为浅灰色,这样烟粒子会和场景雾融合,产生更自然的消散效果。

    总结与进阶建议

    这三个案例的核心思路是:不要试图用粒子模拟真实物理,而是模拟视觉特征。火焰的卷曲、水的表面张力、烟的层次感,都是通过噪声和曲线组合实现的“视觉欺骗”。

    进阶学习路径
    1. 掌握 Data Interface 的使用(如 Grid 3DSkeletal Mesh),可以做出粒子跟随角色骨骼运动的效果
    2. 学习 Custom HLSL 编写,能实现任意自定义物理(比如龙卷风的粒子吸引)
    3. 结合 MetahumanControl Rig,制作角色施法时的特效联动

    最后给个实用建议:每次制作新特效前,先找3-5个真实参考视频(比如油管上的火焰慢动作),逐帧分析粒子的运动轨迹和颜色变化——这比任何教程都管用。

    ---

    常见问题 FAQ

    Q1:为什么我的火焰粒子看起来像飘动的方块,没有卷曲感?
    A:检查是否添加了 Vortex NoiseCurl Noise。另外粒子数量太少也会导致块状感,建议至少5000个粒子。如果使用CPU发射器,换成GPU模式。

    Q2:瀑布效果中粒子会穿透地面,怎么解决?
    A:在 Particle Collision 模块中,启用 Use Collision,碰撞类型选 World Dynamic,并设置 Restitution(反弹系数)为 `0.1`。如果地面是静态网格体,��保它开启了 Simulate Physics

    Q3:烟雾材质很耗性能,如何优化?
    A:将两层噪声纹理合并为一张 Texture Array,在材质中用 Texture 2DArray 采样,减少纹理采样次数。另外降低粒子数量至3000-5000,用更大的粒子尺寸补偿视觉效果。

    Q4:我的Niagara模拟在编辑器里流畅,打包后卡顿,为什么?
    A:检查是否在 Emitter Properties 中勾选了 Requires Persistent IDs,这会增加内存消耗。另外GPU模拟需要显卡支持DX12,在项目设置中确认 Default RHIDirectX 12

    Q5:如何让火、水、烟三者交互?比如火焰点燃水流产生蒸汽?
    A:使用 Niagara Event 系统。在火焰发射器中添加 Generate Death Event,在水发射器中添加 Event Handler,当火焰粒子死亡时触发水粒子的大小和颜色变化。具体做法:在火焰粒子的 Particle Death 模块中,输出 Event ID,然后在水的发射器中用 Event Handler 接收并修改粒子属性。

    声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。