Niagara粒子系统实战:用旋转纸片技术制作立体闪电特效

发布时间:2026/9/12 19:16:55
Niagara粒子系统实战:用旋转纸片技术制作立体闪电特效 做Niagara这些年我最常被问到的一个效果就是闪电。视觉冲击强、应用场景多而且听起来不难但真正动手做的人都知道想做得“像那么回事”特别容易踩坑。这个系列第二期我把主角交给一个很多人没试过的思路旋转的纸片。用Niagara粒子系统把闪电拆成上百片绕轴旋转的薄片拼起来以后你会得到一条会扭动、有体积、边缘发毛的闪电比普通Beam做法好看不止一个档次而且可控性很强。这篇我会把从原理到参数、从材质到灯光、从调优到排错的全过程拆开讲适合刚接触Niagara的特效萌新也适合想换种思路做闪电的老手。1. 闪电特效的破局思路为什么用“旋转的纸片”1.1 传统闪电做法的痛点和瓶颈先说说大家最常用的两种闪电做法。第一种是Beam发射器拉两点引擎自动连成一条线。优点是快缺点是太“均匀”——Beam是连续的一根光带缺乏闪电那种一节一节拐弯的折线感做出来更像霓虹灯管而不是闪电。第二种是Ribbon条带发射器配合样条线或者噪声扰动能做出一定的扭曲感但本质上它仍然是一根细长的条带摄像机正对时还行一旦侧过去看就扁得像纸片一样完全没有体积。可能有人会说那我在材质里加二维噪声做扰动不就行了这个方法我也试过但材质层能做的扰动和粒子层的位置/旋转扰动完全是两回事。材质噪声只能改变贴图颜色的明暗分布骗不过眼睛对“厚度”和“动态结构”的感知。闪电实际是一团随机的电离通道有分叉、有主次、有旋转单靠一张平面贴图很难模拟出这种层次感。所以我在做项目时慢慢倾向一种方案用大量有厚度的粒子堆出闪电的形状。每个粒子是一片很薄的立方体也就是“纸片”沿闪电的走向逐个排列并且每片都绕自己的长轴以不同速度旋转。这些旋转的纸片组合在一起视觉上就形成了一条立体、活络的电弧。这个方法既有体积感又保留了粒子系统天然的高可控性。1.2 “纸片法”的核心原理拆解把“旋转的纸片”拆开其实就是三个关键点粒子位置、粒子朝向、粒子旋转。位置很好理解闪电不是直线它是一段段弯折的折线。我们先把起点到终点分成很多小段每个分段的中点往随机方向偏移就能得出一条锯齿状的闪电主干。然后把每段的位置当成纸片粒子放置的点。这样一片片短而扁的纸片首尾相接就还原了闪电的折线轮廓。朝向是容易被忽视的一步。纸片不能随便朝向否则拼出来的闪电是乱的。我们要让每张纸片的长轴尽可能贴合闪电在该段的方向。比如闪电某一段的方向是右上到左下那这张纸片的长边也应该朝向这个方向。实现方式是用粒子初始化时计算方向向量然后把纸片模型的X轴旋转到该向量上。旋转就更有意思了。闪电不是静止的它整体在扭动每段还有自己细微的抖动。我们给每张纸片设置一个绕自身长轴的自转速度角速度速度在合理范围内随机分布。于是每张纸片都在旋转它们反射的光线也一直在变化闪电看起来就有一种“活”的蠕动感。把旋转速度调快点闪电就变得躁动不安调慢点就相对稳定但依然有呼吸感。1.3 为什么非要用Niagara而不是Cascade老UE版本里大家用Cascade做粒子也不是不能做这个效果但会非常痛苦。Cascade里粒子属性比较固定想给每个粒子额外存一个“方向向量”、再加一个“自转角速度”就得在多个模块之间来回传数据管理很不直观。Niagara把粒子当成结构体属性可以自由扩展给每个粒子存方向、存旋转轴、存速度这些操作完全模块化做起来顺手得多。另外Niagara里有大量内置的噪声和力场模块。比如Curl Noise Force可以直接对粒子位置做湍流位移Perlin Noise可以生成随机数值这些如果放在Cascade里基本要自己写材质表达式或者搞很多LUT难度不是一个量级。Niagara还有CPU/GPU模拟一键切换调试时用CPU看属性定稿后换GPU跑性能也更好控制。所以只要你认真想做这个闪电效果Niagara是绕不开的工具。2. 闪电路径的生成与纸片粒子的铺设逻辑2.1 从两点到一条锯齿状闪电主干先定义最基本的数据闪电的起点和终点。一般场景里闪电是从乌云高度劈到地面的需要两条Scale曲线或者两个Vector参数控制这里我通常会暴露成User参数方便在关卡里根据闪电生成位置直接改。主干生成逻辑可以这样描述把从起点到终点的连线切成N段比如12到20段段数越多闪电可能的拐点越多。然后对每个分割点计算它到起点的比例t在垂直方向或者随机半球方向加一个偏移量。偏移量的幅度我建议用一个衰减曲线来控制越靠近两端偏移越小中间段偏移可以大一些。这样闪电给人的感觉是两端锚定、中段在甩动非常自然。实际操作中我还喜欢加一道Perlin Noise。做法是在粒子的Update阶段用Perlin Noise的值去修改粒子的位置频率设低一点0.1到0.3幅度设200到500这样会让整条闪电主干有缓慢的蠕动。注意这个Noise要基于同一个种子不然每张纸片各扭各的闪电会散架。Niagara里可以用Attribute Seed或Position作为种子源让同一段位置范围内的粒子共享一个Noise值。2.2 分支与次级扰动的实现细节闪电最迷人的地方在于它的分叉。分叉如果在粒子层面逐条生成成本很高。我的办法是先用主发射器生成闪电主干然后用一个独立的副发射器在主干中段的随机节点上派生“子闪电”。副发射器继承了主节点的位置和方向然后从那里朝随机方向生成自己的锯齿路径。这个过程可以递归一到两层但通常一层就足够视觉了。次级扰动方面闪电边缘会有些毛刺感。这个可以靠让纸片的缩放和旋转带一点高频抖动来实现。我给纸片粒子加了一个Random Speed参数范围在0到2之间乘以一个高频Perlin Noise作用在纸片尺寸上。这样每张纸片的宽度、长度都在微幅跳动整体看起来就有发毛的质感。比单纯把模型做成锯齿要自然得多。另外闪电主干末端的纸片颜色和大小都要往暗、往小收。这个用粒子寿命对应的Color和Scale曲线就能做。我习惯在粒子生命周期前20%保持亮白后80%慢慢衰减颜色从蓝白过渡到深蓝紫色尾部可以完全透明。2.3 纸片的旋转控制绕轴、摆动与随机自旋这是整个效果的重头戏。每张纸片的局部坐标里我的长轴方向是X轴纸片厚度方向是Z轴。要让纸片像一张真正的纸一样绕着它的长轴转本质上是让粒子绕自身X轴产生旋转速度。在Niagara里对应的是粒子属性Angular Velocity或Add Torque in Local Space。我推荐用Add Torque in Local Space因为可以精确控制是绕哪个局部轴转而不会误伤其他轴的朝向。参数上默认绕X轴的扭矩给3到8 rad/s随机分布。注意单位是弧度每秒不是角度一开始我也犯过这个错填成30、50结果纸片全在疯狂旋转几乎看不清闪电形状。除了绕长轴的自转我还习惯加一点绕Y轴的摆动数值压低到0.5到1.5模拟闪电整体弯曲时纸片跟随弯曲的“甩动感”。最后再加上一个全局的Random Perturbation也就是对粒子旋转轴方向做一个小角度扰动避免所有纸片转得像发条一样整齐太整齐的旋转看起来就是机械感不像电弧。关于旋转的同步性同一个闪电段内的纸片旋转轴应该接近一致否则会有“拧麻花”的乱闪。这个可以通过给Direction属性赋值后用Direction作为旋转轴来计算扭矩来实现把局部X轴强行对齐到该段方向然后剩余旋转自由全部释放到绕这个轴的旋转上。3. 实战搭建一个可复现的旋转纸片闪电系统3.1 创建Niagara系统和发射器基础配置下面进入实操环节。打开Niagara编辑器新建一个Niagara System选择模板时直接选“从空白系统开始”不要选那些带默认渲染器的模板后面选择更灵活。系统里我建了两个发射器一个CPU发射器管闪电主体纸片一个GPU发射器管附带火花。主体用CPU是因为要方便我们在Update阶段读取粒子的位置和方向来做调试等效果稳定后转成GPU或保持CPU都行。发射器属性里Sim Target选CPU Compute需要能在CPU上自由读写。Duration设为1秒Loop Behavior选Loop这样闪电就会以1秒为周期反复闪烁适合实时预览。1秒的循环频率就是现实的闪电频率参考我一般用它做基础改到0.5到1.5秒之间随机跳动。然后打开Burst SpawnSpawn Count接一个自定义参数我这里叫PaperCount默认200最大值500。粒子总数不要一开始就拉满先跑通再慢慢加。初始化粒子位置的时候需要从起点和终点之间随机插入一个比例位置。具体做法用Random Float in Range生成0到1的Uniform值再用Lerp把起点向量和终点向量插值就能得到闪电路径上随机一点。这时候粒子还没有方向方向要等下一步用相邻点去算。3.2 粒子更新模块的完整参数推荐初始化完成后关键的逻辑都在Update阶段。下面给一套我常用的参数组合来源是多次项目验证过的手感模块参数推荐值备注与作用Curl Noise ForceStrength400让粒子位置产生湍流偏移模拟闪电的扭曲蠕动Frequency0.2频率太低闪得太慢太高会撕裂闪电结构DragDrag Coefficient1.5抑制粒子运动发散保证纸片不会乱飘Add Torque in Local SpaceAxis (X)3~8 rad/s绕自身长轴旋转这是“纸片旋转”的核心Axis (Y)0.5~1.5 rad/s随闪电弯曲做摆动增加甩动感Random PerturbationRotational Perturbation0.05~0.2对旋转轴做细微扰动让旋转更自然ScaleSize12 x 2 x 0.5纸片长12、宽2、厚度0.5比例类似细长纸条LifetimeParticle Lifetime0.4~0.8s闪电单帧存在时间短一点闪烁感更强纸张模型的初始朝向我用一个自定义模块实现先算出当前粒子到闪电终点的方向向量用Vector Normalize得到单位方向再通过Rotate Vector把Mesh的X轴对齐到这个方向。Nigara里可以用Mesh Orientation属性但最直接的办法是在Update里设置Particles.Position、Particles.Scale之后把Particles.Rotation设置成由方向向量生成的Quaternion。这个Quaternion可以在初始化时生成一次不需要每帧都算。材质方面我用的是一个Additive混合的发光材质Emissive Color用一个Noise扰动过的渐变颜色从白蓝到紫色强度拉高到3到5。为了表现中心的超亮核心我在材质里用两个大体同心的圆环做叠加中心是WhiteHot外圈是Bloom更敏感的颜色。加一个可选的Primary Normal扰动让纸片表面有微弱的流动感。双面渲染务必打开不然纸片旋转到背面时直接消失闪电会一段亮一段黑。3.3 渲染器选择Mesh还是Billboard还是Ribbon这个问题值得多说几句。纸片方案里渲染器有三种常见选择Billboard、Mesh和Ribbon。Billboard是永远面向摄像机的正方形片它虽然也可以旋转但旋转的视觉表现力很弱——因为始终正对相机看不出厚度变化。Ribbon适合连续路径但不适合表现纸片各自独立旋转的动态。所以我的首选是Mesh Renderer配一个引擎自带的Cube把Scale Y设得很小厚度约0.3到0.5。这样纸片在旋转过程中会产生明显的透视遮挡和明暗变化闪电的体积感完全来自这个真实几何体。用Box的另一个好处是它有前后两个面在Additive材质下旋转到侧面时投影面积变小、亮度变低看起来就像电弧有粗细变化特别自然。如果你觉得Cube的四个棱角太明显可以把Scale曲线设成两端尖、中间宽或者直接用一张带Alpha的平面贴图但网格上做一点凹凸。我实测下来Scale曲线在生命周期前段大、中后段小的做法最能模拟闪电主干从爆发到衰减的过程。灯光模块我单独讲一下。Niagara里有Light Renderer可以在粒子位置上创建实时点光源。如果把全部粒子都接灯光性能必然崩溃。我采用一个办法在Update阶段用一个Random条件判断只有当粒子的索引编号能被某个数整除比如每15个粒子选1个才触发放置灯光。选中的粒子的灯光衰减半径不要太大500左右即可灯光颜色跟着闪电的Emissive走。这样既能照亮周围物体又不会造成大量光源互相叠加。3.4 场景后处理与氛围补充闪电的效果一半靠粒子一半靠后处理。在项目设置里把Bloom打开Threshold调到1.5到2.0让闪电核心的亮白区域产生光晕。Intensity我一般给1.0到1.2太高会糊成一片。如果你在室外场景还可以加一个简单的径向模糊材质后处理在闪电出现那一帧做短暂拖影模拟视觉残留。另外可以补充一个“闪光弹”爆发效果闪电出现时主粒子也同步生成一圈快速膨胀的环形冲击波。这个用Niagara的Grid 2D Collection或者Sprite发射器都能做我这里只提一个更轻量的替代闪电主干里挑几十个粒子把它们的Scale在生命周期前0.1秒内瞬间放大3~4倍透明度降到0。这样会形成类似电弧“炸开”的闪光不必额外写新的发射器。4. 调参经验与性能优化4.1 手感最好的三套参数组合不同的应用场景对闪电的要求不一样。我整理了三套我用下来相当顺手的组合分别对应“细腻型”、“粗犷型”和“远距离型”。应用场景粒子数量旋转速度Curl强度纸片尺寸循环时间技能特效主闪电200~3004~6 rad/s300~40014 x 2.50.6s环境天气暴风雨闪电350~5006~10 rad/s500~80018 x 31.2s远景装饰闪电80~1202~3 rad/s20020 x 41.5s这套参数的调整逻辑其实很清楚近距离看的闪电需要更多粒子来体现结构细节旋转速度不能太快否则观众看不清纸片关系远景闪电没有近距离细节压力反而需要大尺寸和快速旋转来撑出存在感。天气闪电因为要配合雨幕Curl强度高一点会让闪电看起来更飘忽不稳定。4.2 粒子数量、贴图尺寸与性能取舍粒子数量永远是最贵的成本。200个Cube粒子加上灯光中端显卡上跑个实时场景压力不大但如果一次性有六七道闪电就得想办法削减。我的习惯是先砍粒子数量再砍灯光数量最后才考虑降贴图分辨率。因为“旋转的纸片”这个方案最大的优势就是一片纸片的视觉贡献相当高200片就能组成一条很完整的闪电。贴图方面512x512已经完全够用不需要上1K因为纸片很小最高频的信息肉眼很难注意到。另一个容易忽略的性能坑是碰撞检测。闪电纸片不需要和场景碰撞务必把Collision模块关掉否则无形中增加大量CPU开销。如果需要纸片在闪电末端散开落地我只对最后10%的粒子开启Collision并且是简单的Sphere查询不是复杂的有向距离场碰撞。4.3 让粒子系统真正“活”起来的细节变体除了灯光和颜色让闪电更鲜活的关键是“非同步”。Niagara里一切默认都是同步播放的比如所有粒子同一时间开始旋转就会出现一种整齐划一的僵硬感。破法是多加几个随机参数给每个粒子一个初始随机Rotation Phase给Emitter设一个Duration Random Range比如0.8s到1.2s随机再给Spawn Count也加随机范围。这样一来每道闪电出现的时间、起始转动角度、粒子数量都不一样在环境中反复出现也不会腻。同一套纸片方案还可以改造成龙卷风卷起的碎屑、能量爆炸的飞片甚至流水边的漂浮纸片。只需要把Curl Noise Force的强度调大把粒子初始位置改为从放射方向生成闪电就变成了碎片风暴。这个泛化能力也是我喜欢用纸片方案的原因之一。5. 常见问题与排查技巧实录5.1 纸片旋转后“穿帮”的两种典型表现做这套效果最常见的翻车点就是纸片横七竖八完全看不出闪电形状。症状一纸片像一堆碎纸在空中乱转。这通常是旋转轴没有沿着闪电方向导致的。检查方向向量是否在Initialize阶段正确计算并传入确认粒子的Rotation是否由这个向量生成的四元数赋值而不是只用Angle产生纯旋转。症状二纸片转到某个角度时闪现半透明重影。大概率是双面渲染没开或者材质里把背面裁剪掉了。把Material的Two Sided打开同时确认Blend Mode是Additive而不是Opaque。我调试这种问题时有个习惯先把所有粒子的Spin Rate全部设成0确认闪电静态时的形态正确然后把旋转速度从0.5开始慢慢往上加观察有没有结构崩塌。很多人一上来就把旋转拉到10以上看到乱成一团就以为是方案不行其实只是参数过猛。5.2 闪电闪烁不自然的根源在“同步”如果所有粒子的寿命都是固定的0.5秒那么闪电会像呼吸灯一样非常规律地亮灭效果很假。解决办法是让粒子的可见性和寿命都带上随机系数Lifetime用Random RangeOpacity Curve上叠加一个高频Perlin Noise。还得注意闪烁是“整体亮灭”和“局部亮度变化”的组合整体亮灭对应发射器循环频率局部亮度变化对应粒子透明度曲线的抖动。两者缺一闪电就只剩下机械的脉冲。Niagara里控制整体闪烁很方便Emitter State中的Duration设置成随机范围再去掉“同步Spawn”选项让每次Loop的起始时间自然错开。如果还嫌不过瘾可以给材质加一个Lightning Flicker节点把Time输入再加上一个有大振幅、高频的Noise作用在Emissive强度上效果就是同一帧内不同纸片的亮度也在高频跳动。5.3 透明排序与深度遮挡异常Additive材质没有深度写入所以当闪电在角色身后时可能会出现“隔着角色身体透出闪电”的情况。这是半透明物体的通用问题不只在Niagara里有。解决思路有两条第一场景里角色模型改成Two Sided半透明通道但这样成本高第二利用Niagara的Advanced Rendering设置里Translucency的Sort Priority把闪电的渲染优先级排在不透明物体之后保证至少正常遮挡。如果是纯环境闪电不与玩法角色交互那完全可以把闪电粒子系统放到独立一个半透明通道并创建UTextureRenderTarget2D用Custom Depth做遮挡剔除。日常工作里我通常会给闪电材质加一个Scene Depth节点让闪电在有遮挡物的区域透明度归零。这个方法简单有效性能损失很小。5.4 Niagara不同版本导致的“陷阱”如果你用的UE版本比较老或者特别新有些模块名会有差异。UE5.2之前Mesh Renderer叫MeshRenderInfoUE5.2之后模块做了整理名字变成了Mesh Renderer对应的属性名也更新了。老写法里有一部分变量如MeshOrientation在更新版里被简化掉了如果你抄老教程发现属性不存在先看看Attribute面板里是不是剃掉了Deprecated项。Add Torque in Local Space在UE4.26里叫Torque in Local Space功能一样名字不同。Curl Noise Force老版本里参数项较多区分Solution和Solver新版也做了收敛。遇到版本问题最常见的解法就是搜索官方文档中对应版本号的模块列表。我一般在打开Niagara后会首先打开Emitter的Attribute面板把所有可用的属性过一遍确认要用的字段在不在。不要跳过这一步版本迁移的失误大多出在这里。另外一个容易被坑的点CPU粒子的Angular Velocity单位是弧度每秒查看预览数值时如果你不熟可以先用小数值如1测试确认旋转方向后再放大。GPU模拟时Angular Velocity的单位是度每秒跟CPU不一致切换模拟目标时要把参数除以57.3左右。这个细节我踩过两次确实容易让人怀疑人生。我个人在实际操作中的最深体会是闪电这种“失控感”很强的效果恰恰需要严格的底层控制。旋转纸片方案胜在把不可预测的闪电拆成了一个个可预测的小单位每张纸片转多快、往哪转、什么时候隐去都能单独掌控。最后再分享一个小技巧别忘了把PaperCount、Curl Strength、Spin Rate这几个最常用的参数暴露成User Parameter并放到一个名为闪电控制的分组里这样在关卡里调闪电强度时就不用一遍遍打开Niagara编辑器了。这个系列后续如果再更新我大概率会拿纸片方案去扩展成风沙龙卷或者雷电法阵同一个粒子逻辑在不同场景里换皮就能用真的越用越顺手。