UE5 Niagara系统实战:从零打造动态烟雾特效的完整指南 📅 2026/7/15 5:12:49 1. 项目概述与核心思路最近在做一个需要氛围感的项目场景里缺了点“仙气”琢磨着得加点动态烟雾。翻了一圈商城免费的资源要么效果太假要么性能开销吓人收费的又觉得为一个小功能不值当。干脆自己动手用UE5的Niagara系统从头搓一个。这玩意儿听起来高大上其实拆解开来核心就是“纹理动画”加“粒子运动”再套上一层半透明材质。网上教程不少但要么跳步太快要么只讲操作不讲原理新手跟着做容易卡在莫名其妙的地方。今天我就把自己从零搭建、调试到优化的完整过程包括每一步背后的逻辑和踩过的坑都详细记录下来。目标很简单让你看完就能做出一个会自然飘动、性能可控的烟雾特效并且真正理解为什么这么做。这个教程会完全围绕Niagara和材质编辑器展开。你需要对UE5的界面有基本了解知道怎么创建材质和Niagara系统就行。我们不用任何第三方插件或复杂脚本全部使用引擎内置节点。最终效果是一个可以调节密度、速度、颜色和形态的动态烟雾适合用在篝火、蒸汽、魔法效果或者任何需要朦胧氛围的场景。我会把关键的材质节点图完整贴出来并解释每一个节点的作用确保你不仅能复制还能举一反三。2. 核心原理与系统选型为什么是Niagara加材质在UE里做动态效果常见的有几种路子用序列帧动画贴图、用蓝图控制顶点动画、或者用粒子系统。序列帧动画灵活度低资源量大蓝图控制顶点动画对性能不友好且难以做出自然的随机运动。而粒子系统特别是UE5的Niagara是专门为这类动态、随机、大量重复的视觉效果设计的。它把每个烟雾颗粒粒子的生命周期、运动、外观都交给一个可编程的系统管理我们只需要定义好规则。2.1 Niagara系统的核心优势Niagara相比老的Cascade粒子系统最大的特点是“可视化编程”和“数据驱动”。你不需要写代码通过连接各种模块Module就能控制粒子的行为。对于烟雾来说我们需要的关键模块包括Spawn生成控制烟雾在何时、何地、以何种速率产生。Update更新在粒子存活期间每一帧如何更新它的位置、速度、大小、颜色等属性。Render渲染决定粒子最终在屏幕上如何被绘制出来这里就会链接到我们自制的烟雾材质。选择Niagara的另一个重要原因是它的性能可预测性和可优化性。我们可以精确控制同时存在的最大粒子数、粒子的渲染方式比如是否启用GPU粒子这对于避免特效成为场景的性能瓶颈至关重要。2.2 材质的作用赋予粒子“形”与“色”Niagara负责让一堆点动起来但这些点看起来像什么是透明还是半透明是什么颜色和纹理这就需要材质Material来定义了。烟雾材质的核心是“半透明着色模型”和“纹理动画”。半透明Translucent这是必须的。只有半透明着色模型才能让烟雾粒子之间、烟雾与场景之间产生正确的混合叠加形成朦胧感。如果错选为不透明Opaque烟雾就会变成一块块实心的纸片。纹理动画一张静态的烟雾贴图会很死板。我们需要让贴图在粒子表面“流动”起来模拟烟雾内部细微的翻滚、扩散运动。这通常通过Panner平移节点驱动纹理坐标UV来实现。顶点偏移可选但推荐为了增加体积感和动态变形我们可以让烟雾网格的顶点也产生一些缓慢的、随机的偏移这能打破粒子作为“刚性面片”的僵硬感让烟雾形态更有机。所以我们的技术路线就明确了创建一个Niagara粒子系统来模拟烟雾粒子的生成与基础运动再创建一个半透明材质利用纹理动画和顶点偏移来塑造每个粒子的视觉细节最后将材质赋予粒子进行渲染。3. 烟雾材质制作全流程与节点详解材质是烟雾的“皮肤”我们先把它做好这样在Niagara里调试时就能立刻看到视觉反馈。3.1 创建材质与基础设置在内容浏览器右键选择“材质”命名为M_Smoke_Volumetric。双击打开材质编辑器。首先在细节面板设置材质域Material Domain为“表面”Surface着色模型Shading Model为“半透明”Translucent。将混合模式Blend Mode设置为“半透明”Translucent。这是最关键的一步它决定了材质如何与背景混合。为了获得更柔和的边缘和深度消散效果我们通常需要修改光照模式。在细节面板找到“光照模型”Lighting Model将其设置为“体积非定向”Volumetric NonDirectional。这个模式特别适合烟雾、云朵这类没有明确表面法线的体积状半透明物体它能提供更自然的光照响应。注意如果你的UE5版本较新或项目设置不同“体积非定向”选项可能位于“着色模型”下拉菜单中或者需要先启用“支持体积材质”之类的项目设置。如果找不到暂时使用“默认光照”也可以但边缘可能会硬一些。3.2 构建纹理动画网络这是材质最核心的部分目的是让一张静态的烟雾贴图“活”起来。纹理采样在材质图表中右键搜索Texture Sample。我们需要一张烟雾纹理。一个非常好的起点是引擎自带的T_SmokeSubUV_8x8可以在内容浏览器的“查看选项”中勾选“引擎内容”来找到它路径通常在Engine/Content/EditorResources附近。这张图本身是8x8的序列帧但我们只把它当作一张有丰富细节的噪声图来用。将纹理拖入图表或通过Texture Sample节点指定。原理这张纹理包含了烟雾所需的灰度变化和细节。白色区域代表烟雾浓密处黑色代表稀薄或透明处。我们通过移动它的UV坐标让这些浓淡区域在粒子表面滑动形成动态变化。创建平移动画右键搜索Panner节点。这个节点接收一个UV坐标输入和两个速度参数Time X Speed Y Speed输出随时间平移后的新UV坐标。将Texture Sample节点的UV引脚连接到Panner节点的UV输入。我们需要一个随时间变化的信号来驱动平移。右键搜索Time节点将其输出连接到Panner节点的Time输入。设置Panner节点的X Speed和Y Speed为较小的值比如(0.1, 0.05)。速度太快会像快进的云太慢则没有动感。X和Y速度不同可以创造出对角线方向的流动更自然。增加随机性与复杂性单一的平移方向会很假。我们可以通过叠加多个不同速度、不同方向的Panner或者对UV进行扭曲来增加细节。方法A叠加复制一组Texture Sample和Panner使用另一组不同的速度例如(-0.07, 0.03)。然后使用LinearInterpolateLerp节点或Multiply、Add节点将两个纹理采样结果混合。混合时可以用一张Noise纹理作为遮罩让混合不均匀。方法B扭曲在第一个Panner之后添加一个Rotator节点让UV产生缓慢旋转。或者使用World Position经过简单计算后偏移UV模拟世界空间下的微风效果。个人心得对于入门我建议先从“方法A”的简单叠加开始。创建两个Panner一个慢速一个快速但强度弱。将慢速的采样结果作为基础形状快速的采样结果乘以一个较小的系数如0.3后加到基础上。这样既有整体缓慢的飘移又有内部细微的翻滚层次感就出来了。3.3 构造不透明度Opacity通道烟雾的透明变化是其真实感的关键。我们利用纹理采样的灰度值R通道来控制不透明度。将主纹理采样节点或混合后的最终颜色的RGB输出断开我们暂时只关心它的灰度信息。将其R通道因为烟雾贴图通常是灰度的R、G、B值相同拖出连接到材质节点的Opacity输入引脚上。此时你会发现烟雾可能太“实”或太“虚”。我们需要对灰度值进行重新映射Remap。在R通道输出后添加一个Multiply和Add节点。Multiply用于控制对比度。值大于1会让白的更白、黑的更黑烟雾对比更强烈值在0到1之间会压缩对比度让烟雾更均匀、柔和。可以从1.5开始调试。Add用于控制整体透明度偏移。负值会让整体更透明正值更不透明。通常设为-0.2到0之间让黑色部分完全透明。进阶技巧深度消散为了让烟雾在靠近物体或地面时能自然淡出可以启用“材质属性”中的“不透明蒙版剪裁值”Opacity Mask Clip Value但更常用的方法是使用“像素深度偏移”Pixel Depth Offset或与场景深度进行混合。对于新手一个简单的替代方案是在Niagara中根据粒子的生命周期Age来动态控制材质的整体不透明度乘数一个标量参数让粒子在出生和死亡时淡入淡出。3.4 构造颜色与自发光基础颜色将处理好的纹理灰度信息即连接到Opacity的那个值复制一份连接到一个LinearInterpolateLerp节点的Alpha输入。Lerp节点的A和B输入分别连接两种颜色例如A为深灰色0.2,0.2,0.2B为浅灰白色0.8,0.8,0.8。这样烟雾浓的地方灰度值高呈现B色淡的地方呈现A色有了基本的色彩变化。自发光为了让烟雾在暗部也能有体积感可以添加微弱的自发光。将上述基础颜色输出复制一份乘以一个很小的系数如0.1然后连接到材质节点的Emissive Color。注意系数不要太大否则烟雾会看起来像发光体。参数化强烈建议将颜色、速度、对比度等数值都转换为材质参数右键搜索ScalarParameter或VectorParameter。这样你无需重新编译材质就可以在材质实例或Niagara中实时调节这些属性效率极高。将Panner的速度、Multiply的系数、Lerp的颜色都替换成参数节点并给它们起好名字如SmokePanSpeed,OpacityContrast,SmokeColorDark,SmokeColorLight。3.5 添加顶点偏移模拟体积感这一步能让平面的粒子面片产生形变更像一团体积雾。在材质图表中我们需要影响World Position Offset引脚。这需要将着色模型临时改为“默认光照”或“无光照”才能看到该引脚修改完可以改回来引脚会保留。思路是使用一张3D噪声纹理如引擎自带的T_3DNoise来扰动顶点的世界位置。采样3D噪声需要世界位置坐标。添加Texture Sample节点选择3D噪声纹理将其UV输入连接到WorldPosition节点。同样用一个缓慢的Panner连接Time节点来移动3D噪声的采样让形变也动起来。将采样结果的R通道一个-1到1之间的值乘以一个非常小的系数如0.01这个系数控制形变强度。然后将结果输出到World Position Offset。注意事项顶点偏移非常消耗性能尤其是对大量粒子使用时要极其谨慎。强度系数务必从0.001这样极小的值开始测试。对于远处或作为背景的烟雾完全可以关闭此功能。在我们的案例中可以将其做成一个由参数控制的开关。至此一个功能完整的烟雾材质节点网络就搭建完毕了。编译并保存材质。你可以先创建一个材质实例调整我们暴露出来的参数看看颜色、速度、透明度变化是否如你所愿。4. Niagara粒子系统搭建与参数配置材质准备好后我们进入Niagara部分创造一群被赋予生命的烟雾粒子。4.1 创建Niagara系统与发射器在内容浏览器右键选择“FX” - “Niagara系统”命名为NS_Smoke_Floating选择“空模板”创建。双击打开系统。在系统面板我们需要添加一个发射器。点击“发射器”按钮选择“从模板生成”然后选择“Sprite渲染器”Fountain。这个模板包含了我们所需的基础模块。将其重命名为SmokeEmitter。在左侧的“发射器更新”和“粒子更新”区域我们会看到一堆预制模块。先删除一些我们不需要的比如Color我们用材质控制颜色、Sprite Size我们用缩放模块、Velocity我们重新定义运动。4.2 配置粒子生成Spawn属性在“发射器更新”中找到Spawn Rate模块。这控制每秒生成多少粒子。对于持续飘散的烟雾我们通常使用一个恒定速率。将Spawn Rate设置为一个适中的值比如10。这意味着每秒生成10个新烟雾粒子。为什么不是一次性爆发烟雾是持续产生的恒定速率模拟了源头的持续排放。如果你要做爆炸烟雾可以改用Burst模块。在“粒子生成”中我们需要初始化每个粒子的属性。Initialize Particle模块确保Lifetime生命周期被设置。一个合理的烟雾粒子应该存在几秒钟。将其分布模式设为“均匀范围”最小值3最大值7。这样粒子寿命有随机性消散不会整齐划一。Sprite Size模块初始化粒子大小。同样用均匀范围比如最小值30最大值80单位是厘米。大小不一更自然。Add Velocity模块给粒子一个初始速度。对于缓慢上升的烟雾可以设置Z轴向上为正速度如20-50 cm/s。X和Y轴可以给一个很小的随机速度-5到5模拟轻微的横向扩散。4.3 配置粒子更新Update属性让烟雾“飘”起来这是模拟飘动感的核心区域。我们需要在“粒子更新”中添加和配置模块。基础运动Update Sprite模块是默认存在的确保粒子位置会根据其速度每帧更新。添加阻力Drag这是实现烟雾“飘”而非“飞”的关键物理效果。添加“力”分类下的Drag模块。阻力系数设为0.5到2之间。系数越大粒子速度衰减越快感觉越“粘稠”。烟雾阻力应该较大使其快速失去初始速度然后主要受其他力影响。添加恒定力Gravity/Force模拟浮力或微风。对于上升的烟雾热烟我们需要一个向上的力来对抗重力。添加Constant Force模块设置一个向上的力例如Z轴为30 cm/s²。这个力会持续作用使粒子获得一个向上的加速度。重要同时你需要禁用或抵消重力。在“系统更新”中找到Simulation Stage下的Apply Gravity模块将其强度设置为0或者添加一个Constant Force模块设置一个向下的力如Z轴 -980 cm/s²来精确抵消引擎重力。否则你的烟雾会在上升力和重力的拉扯下行为怪异。添加噪声力Noise Force这是制造烟雾随机飘动、蜿蜒上升的灵魂模块。添加Vortex Noise Force或Curl Noise Force模块。Vortex Noise Force会产生漩涡状的力场让烟雾产生旋转、卷曲的效果。可以调节强度、频率和衰减。Curl Noise Force基于噪声的旋度场能产生更自然、有机的随机扰动非常适合烟雾和流体。我更喜欢用这个。参数设置示例Curl NoiseNoise Strength: 50-150。控制扰动的强度。Noise Frequency: 0.1-0.3。控制噪声图案的尺度值越小大尺度的平滑扭曲越多值越大小尺度的快速抖动越多。Noise Modulation: 可以连接一个基于粒子生命周期的曲线让噪声力在粒子生命中期最强出生和死亡时减弱更符合物理。生命周期内的大小与透明度变化添加Scale Sprite Size和Color模块这里Color主要控制透明度。在Scale Sprite Size中将缩放模式设为“曲线”并编辑曲线。通常粒子出生时快速放大0到0.2秒内从0到1然后缓慢增长1到1.2最后在死亡前缓慢缩小生命末期从1缩到0。在Color模块中我们主要使用Alpha通道透明度。同样使用曲线控制。粒子出生时Alpha从0快速到1淡入生命中期保持1死亡前从1缓慢降到0淡出。RGB颜色可以保持白色因为最终颜色由我们的材质决定。4.4 配置粒子渲染Render属性在“粒子渲染”中找到Render Sprites模块。这是将我们之前做的材质与粒子关联起来的地方。在Material参数下选择我们创建的M_Smoke_Volumetric材质。SubImage设置因为我们使用的T_SmokeSubUV_8x8是子UV纹理虽然当单张用这里可以保持为1x1。如果你真的想用它的序列帧功能可以设置为8x8并在粒子更新中添加SubImage Index模块来控制帧播放。Alignment对齐方式对于烟雾通常选择Velocity速度对齐或Custom Facing Vector自定义朝向。速度对齐会让粒子面片始终垂直于其运动方向这在粒子快速运动时很自然。但对于缓慢飘动的烟雾使用Screen屏幕对齐或Custom Facing Vector并指向摄像机能保证粒子始终以最大面积面向玩家视觉效果更饱满。我通常选择Screen。Sort Mode排序模式对于半透明物体正确的排序至关重要以避免渲染错误。设置为View Distance按到摄像机的距离排序是最通用和稳定的选择。4.5 系统级优化与调试设置粒子数量上限在发射器属性中找到Max Particles最大粒子数设置一个合理值如500。防止因为生成过快或生命周期过长导致粒子无限累积耗尽性能。使用GPU粒子对于像烟雾这样数量多、逻辑简单的粒子使用GPU模拟能极大提升性能。在发射器属性的Simulation Target中选择GPU。注意切换到GPU后部分模块可能不被支持会有警告需要调整或替换为GPU兼容的版本。调试视图Niagara编辑器提供了强大的调试工具。点击视图左上角的“调试”选项可以显示粒子的速度向量、生命周期、受力方向等这对于理解粒子行为和调整参数至关重要。5. 材质与Niagara的联调实战现在将你的NS_Smoke_Floating系统拖入关卡。你应该能看到基本的烟雾效果了但可能还不够理想。联调是关键。5.1 在Niagara中动态控制材质参数我们之前将材质中的关键参数如平移速度、颜色、对比度都暴露成了参数。现在可以在Niagara中动态地改变它们让每个粒子都有所不同效果更丰富。在Niagara发射器的“粒子生成”或“粒子更新”中添加Dynamic Material Parameters模块。在这个模块里你可以链接到材质实例中的标量或向量参数。例如你可以在粒子生成时给SmokePanSpeed一个随机范围如X速度0.05到0.15Y速度0.02到0.08让每个粒子的纹理流动速度不同。在粒子更新时根据粒子的生命周期用曲线驱动OpacityContrast不透明度对比度让粒子在中年时对比最强出生和死亡时对比减弱。根据粒子的初始速度或高度给SmokeColorLight亮部颜色一个微妙的色调变化如低处偏灰蓝高处偏暖白。5.2 通过曲线与随机性增加自然度自然界的烟雾没有完全相同的两团。充分利用Niagara的“分布”类型均匀、随机、曲线、梯度。大小随机我们已经做了。生命周期随机我们已经做了。初始速度随机我们已经做了。受力随机可以在Noise Force模块的Noise Strength或Frequency上添加一个每粒子随机乘数。透明度曲线确保淡入淡出曲线不是线性的而是缓入缓出的使用曲线编辑器的贝塞尔手柄调整这样过渡更平滑。5.3 性能与视觉的平衡点粒子数量 vs 粒子大小与其用1000个很小的粒子不如用200个适当大小的粒子。减少粒子数量是提升性能最有效的手段。通过增大粒子大小和优化材质来弥补。材质复杂度顶点偏移World Position Offset是最耗能的材质操作之一。如果性能吃紧首先考虑关闭它或者大幅降低其强度。纹理采样次数也要控制两到三层混合通常是上限。LOD细节层次在Niagara系统属性中可以设置LOD。当系统距离摄像机很远时可以自动降低生成速率、减少最大粒子数、甚至切换到更简单的材质实例。剔除Culling确保粒子系统设置了合理的边界盒Bounds并且启视锥体剔除Frustum Culling。不要让不可见的粒子参与计算。6. 常见问题排查与进阶技巧即使按照步骤操作你也可能会遇到一些典型问题。这里是我踩过坑后的经验总结。6.1 问题速查表问题现象可能原因解决方案烟雾看起来像一堆坚硬的卡片/面片没有融合感。1. 材质混合模式不是“半透明”。2. 粒子排序模式错误。3. 材质不透明度设置不当整体太“实”。1. 检查材质Blend Mode是否为Translucent。2. 在Render Sprites模块中将Sort Mode设为View Distance。3. 调整材质Opacity通道的Add节点增加负偏移或降低Multiply系数。烟雾颜色发黑或异常。1. 材质光照模式不适合。2. 场景光照不足。3. 自发光颜色或基础颜色设置错误。1. 尝试将材质光照模型改为Volumetric NonDirectional或Unlit无光照测试。2. 在场景中放置一个天光Skylight或后期处理体积调整曝光。3. 检查材质节点中颜色值是否在合理范围0-1避免过暗。烟雾粒子运动僵硬直线上升。1. 缺少噪声力或湍流模块。2. 阻力Drag系数太小。3. 作用力太单一或太强。1. 确保添加了Curl Noise Force或Vortex Noise Force模块并调整强度和频率。2. 增加Drag模块的系数使粒子更快减速。3. 检查重力是否被正确抵消向上的恒定力不宜过大。粒子闪烁或排序错乱Z-fighting。1. 半透明物体渲染顺序冲突。2. 多个粒子系统或面片距离太近。1. 确保Sort Mode为View Distance。2. 在材质中尝试微调“不透明蒙版剪裁值”或启用“像素深度偏移”需谨慎影响性能。3. 避免粒子面片在3D空间内完全重叠通过大小和位置随机性分散。性能开销巨大帧率下降明显。1. 粒子数量过多。2. 材质过于复杂特别是顶点偏移。3. 未使用GPU粒子。1. 大幅降低Spawn Rate和Max Particles。2. 简化材质移除或降低顶点偏移强度减少纹理采样层数。3. 将发射器Simulation Target改为GPU检查模块兼容性。纹理动画不动或速度不对。1.Panner节点未连接Time输入。2.Panner速度参数为0或过小。3. 材质参数未正确传递到实例或Niagara。1. 检查材质图表确保Panner节点的Time引脚有连接通常是默认的Time节点。2. 增大Panner的Speed X/Y值。3. 在材质实例和Niagara的Dynamic Material Parameters模块中检查参数名是否匹配数值是否被覆盖。6.2 进阶优化与效果提升技巧使用材质函数封装常用节点如果你发现Panner叠加噪声扭曲Lerp颜色这套组合拳经常用可以把它做成一个材质函数Material Function。比如创建一个叫MF_SmokeTextureAnim的函数输入基础纹理、速度、强度输出处理后的颜色和透明度。这样主材质图表会更简洁也便于复用。利用粒子事件驱动复杂行为Niagara支持事件Events。例如你可以设置当两个粒子距离过近时触发一个“合并”事件让其中一个粒子提前消亡并放大另一个模拟烟雾团的融合。这需要更深入的学习但能做出非常高级的效果。结合距离场Distance Field实现交互让烟雾对场景中的物体或角色做出反应。在材质中使用DistanceToNearestSurface节点获取粒子到最近物体表面的距离然后用这个距离来影响烟雾的不透明度或颜色。例如让烟雾在靠近墙壁时变淡或绕开。这需要项目启用“生成距离场”选项。制作多层烟雾系统不要试图用一个发射器模拟所有烟雾。创建两到三个发射器一个发射大而慢、生命周期长的基础烟团一个发射小而快、生命周期短的细节烟丝甚至第三个发射极慢、极淡的背景烟霭。将它们组合在一个Niagara系统内层次感和细节会大幅提升且比单纯增加一个发射器的粒子数更高效。调试是一个反复的过程。记住一个黄金法则每次只调整一个参数观察变化。从整体运动Niagara力场开始调感觉对了再调外观材质颜色透明度最后微调细节纹理动画速度、粒子大小变化曲线。把系统拖到不同的光照和背景下测试确保它在各种环境下都表现可靠。当你看到自己亲手打造的烟雾在场景中悠然飘动时那种成就感就是最好的回报。