游戏盾牌格挡特效:用 Niagara 模拟能量反弹与碎片飞溅

上周有位学员在群里发了一条消息:“老师,我做的盾牌格挡效果像纸片糊的,敌人砍过来一点反馈感都没有。” 这其实是一个很典型的问题——很多同学在制作防御类特效时,只关注了盾牌本身的发光,却忽略了“碰撞瞬间”的冲击力表现。今天我们就用 UE5 的 Niagara 系统,从零搭建一个具备能量反弹与碎片飞溅的盾牌格挡特效。我会直接给出操作参数和节点连接方式,你跟着走一遍就能出效果。

一、搭建基础框架:Niagara 发射器与碰撞事件绑定

1.1 创建发射器并配置碰撞检测

打开 UE5.4,在 Content Browser 中右键 → FX → Niagara System → 选择 “New Niagara System from selected Emitters” → 模板选 “Empty”。命名为 `NS_ShieldBlock`。

双击打开后,在 Emitter 属性面板中:

  • Sim Target:选择 `CPUSim`(CPU 模拟,便于调试)
  • Initialize Particle 模块:将 `Lifetime` 设为 `0.3-0.6`(随机范围),`Sprite Size` 设为 `10-20`(适配盾牌碰撞点大小)
  • Spawn Rate:设�� `50-80`(每秒生成粒子数,碰撞瞬间需要密集爆发)
  • 关键步骤:添加 Collision 模块。在 Emitter 栈中右键 → `Add Module` → `Collision` → 选择 `Collision with World`。参数设置:

  • Collision Mode:`Collision with World Geometry`(与场景几何体碰撞)
  • Restitution:`0.8`(弹性系数,让粒子反弹更明显)
  • Friction:`0.1`(减少能量损耗)
  • Collision Group:保持默认 `WorldStatic`,但如果你想让粒子只与特定物体碰撞(比如敌人武器),可以新建一个自定义碰撞通道。
  • 1.2 在角色蓝图中触发特效

    打开你的角色蓝图(假设是 `BP_Player`),添加一个 `Niagara Component` 变量,命名为 `ShieldBlockFX`。在 Event BeginPlay 中:

    ShieldBlockFX = Spawn Niagara System at Location(NS_ShieldBlock, GetActorLocation())
    ShieldBlockFX -> Activate(false) // 先禁用,等待触发
    

    当检测到格挡输入时(比如按 Q 键),调用:

    ShieldBlockFX -> Activate(true)
    ShieldBlockFX -> Set Niagra Variable Vec3("HitLocation", ImpactPoint)
    ShieldBlockFX -> Set Niagra Variable Float("HitIntensity", 1.0)
    

    这里 `HitLocation` 和 `HitIntensity` 是我们要在 Niagara 中暴露的自定义参数。回到 Niagara 编辑器,在 User Parameters 面板中添加:

  • `HitLocation`:类型 `Vector`,默认 `(0,0,0)`
  • `HitIntensity`:类型 `Float`,默认 `1.0`
  • 在 `Spawn Particles` 模块中,将 `Spawn Location` 改为 `User.HitLocation`。这样粒子就会精确生成在碰撞点。

    Niagara 碰撞参数配置面板

    二、能量反弹特效:方向计算与动态拖尾

    2.1 基于法线计算反弹方向

    默认的碰撞后粒子会沿随机方向弹开,但盾牌格挡应该有一个“向攻击方向反推”的视觉逻辑。我们需要在 `Particle Update` 阶段修改速度方向。

    在 Emitter 栈中添加 `Particle Update` 模块 → 选择 `Add Dynamic Input` → `Vector from Float`。新建一个自定义脚本 `CalculateRebound`。双击进入脚本编辑,连接如下节点:

    输入:Particle Position, HitLocation, HitNormal
    输出:ReboundDirection

    1. 获取粒子当前位置与 HitLocation 的差向量:Position - HitLocation 2. 将这个向量投影到 HitNormal 上:DotProduct(向量, HitNormal) * HitNormal 3. 用原始向量减去投影向量,得到沿平面方向的分量:原始向量 - 投影 4. 最终反弹方向 = 沿平面方向分量 0.6 + HitNormal 0.4(混合系数可调)

    回到 Niagara,在 `Initialize Particle` 模块中,将 `Velocity` 设为 `User.CalculateRebound * 500`(速度大小根据 `HitIntensity` 缩放)。这样粒子会优先沿盾牌法线方向反弹,而不是随机四散。

    2.2 添加拖尾粒子增强动感

    在同一个 Emitter 中,右键 → `Add Emitter` → `Empty`,命名为 `TrailEmitter`。这个发射器专门生成拖尾粒子,跟随主粒子的运动轨迹。

    关键设置:

  • Spawn Mode:`Rate`,设为 `0`(不主动生成)
  • Particle Spawn 中,勾选 `Use Particle Spawn Event`,然后在主 Emitter 的 `Particle Spawn` 模块中,添加 `Generate Spawn Event` → 事件名 `TrailEvent`
  • TrailEmitter 的 `Spawn Particles` 模块:`Spawn Event` 选择 `TrailEvent`,`Spawn Rate` 设为 `3-5`(每个主粒子生成3-5个拖尾粒子)
  • 拖尾粒子的生命周期设为 `0.1-0.2`,颜色从亮蓝(R=0.2,G=0.6,B=1.0)渐变到透明。大小从 `8` 衰减到 `2`。这样当主粒子碰撞弹开时,身后会拖出一道光痕,强化能量流动感。

    拖尾粒子参数与效果预览

    三、碎片飞溅:物理模拟与材质细节

    3.1 生成刚性碎片粒子

    新建一个 Emitter `DebrisEmitter`。这次我们不使用 Sprite 渲染,而是使用 Mesh Renderer → 选择 Static Mesh `SM_Cube`(引擎自带的小立方体,或者导入一个盾牌碎片模型)。

    物理参数:

  • Sim Target:`CPUSim`
  • Gravity:`(0,0,-980)`(模拟重力)
  • Lifetime:`0.5-1.5`
  • Spawn Rate:`20-30`(碰撞瞬间爆发)
  • 在 `Initialize Particle` 中,设置初始速度:

    Velocity = Random Unit Vector  300 + HitNormal  200
    

    这样碎片会沿法线方向集中飞散,同时带有随机扩散。

    3.2 旋转与碰撞反馈

    为了让碎片看起来更真实,添加 `Ribbon` 模块(实际上是 `Mesh Rotation` 模块):

  • Rotation:`Random Float in Range(0, 360)`(初始随机角度)
  • Angular Velocity:`Random Float in Range(-500, 500)`(随机自旋速度)
  • 在 `Collision` 模块中,将 `Restitution` 设为 `0.3`(碎片落地后不会弹得太高),`Friction` 设为 `0.8`(快速停住)。同时勾选 `Generate Collision Events`,这样碎片撞击地面时可以触发音效或二次特效(比如尘土粒子)。

    3.3 材质发光效果

    碎片的材质需要体现“能量碎片”的感觉。新建一个材质 `M_Debris_Glow`,核心节点:

  • Base Color:`Lerp(深灰, 亮蓝, Time * 0.5)`(随时间从灰变蓝)
  • Emissive Color:`(1,0.5,0.2) * 3`(橙色高亮发光)
  • Opacity Mask:使用 `Noise` 节点生成随机纹理,让碎片边缘半透明
  • 在 Niagara 的 `DebrisEmitter` 中,将 `Material` 设为 `M_Debris_Glow`,并在 `Particle Update` 中暴露一个 `Particle Color` 参数,用 `Random Vector` 让每个碎片颜色略有差异(R=0.8-1.0, G=0.4-0.6, B=0.1-0.3)。

    碎片飞溅与发光材质效果

    四、性能优化与多层效果叠加

    4.1 粒子数量控制

    在 `Spawn Particles` 模块中,添加 `Kill Particles` 节点,判断条件:

  • 如果 `Particle Age > Lifetime`,直接销毁
  • 如果粒子距离发射点超过 `500` 单位,也销毁(避免溢出世界)
  • 在 `DebrisEmitter` 中,将 `Max Particles` 设为 `100`,超过数量时自动淘汰旧粒子。

    4.2 多发射器协同

    实际项目中,一个完整的格挡特效通常包含3-4层:

  • 主光效发射器:圆环扩散+中心光柱(使用 `Ribbon Renderer`)
  • 能量反弹发射器:我们上面做的拖尾粒子
  • 碎片发射器:物理碎片+发光材质
  • 冲击波发射器:使用 `Sprite Renderer` 的圆形纹理,快速缩放并淡出
  • 在 `NS_ShieldBlock` 中,将所有发射器放在同一个 Niagara System 中,通过 `User Parameters` 统一控制位置和强度。这样在角色蓝图中只需一次调用就能触发完整效果。

    五、常见问题 FAQ

    Q1:粒子碰撞后直接穿模,不反弹怎么办?
    A:检查 Collision 模块中的 `Collision Mode` 是否设为 `Collision with World Geometry`。另外确认你的盾牌网格体有碰撞体(在 Static Mesh 编辑器中查看 Collision 预设)。如果使用 Character 碰撞,需要将 `Collision Channel` 改为 `Pawn`。

    Q2:拖尾粒子看起来断断续续,不连贯?
    A:在 TrailEmitter 的 `Spawn Particles` 模块中,将 `Spawn Rate` 提高到 `8-10`,同时降低拖尾粒子的 `Lifetime` 到 `0.05-0.1`。另外确保主粒子的运动速度不低于 `200`,速度太慢拖尾会显得稀疏。

    Q3:碎片飞溅的方向总是向上,没有向攻击方向反弹?
    A:在 `DebrisEmitter` 的 `Initialize Particle` 中,检查速度计算:`Random Unit Vector Speed + HitNormal 200`。确保 `HitNormal` 是从碰撞事件中正确获取的法线方向(在角色蓝图中将 `ImpactNormal` 传入 Niagara 的 `User.HitNormal` 参数)。如果法线方向反了,乘以 `-1` 即可。

    Q4:特效在手机上卡顿严重,如何优化?
    A:首先将所有发射器的 `Sim Target` 改为 `GPU Sim`(移动端 GPU 性能通常优于 CPU)。其次将 `DebrisEmitter` 的 `Max Particles` 降到 `30`,`TrailEmitter` 的拖尾数量降到 `2-3`。最后关闭 `Collision` 模块中的 `Generate Collision Events`,改用 `Location` 模拟碰撞后位置。

    Q5:如何让特效颜色随武器元素变化(比如火盾、冰盾)?
    A:在 Niagara User Parameters 中添加 `Color` 参数(类型 `LinearColor`),在角色蓝图中根据武器类型设置。然后在每个发射器的 `Particle Update` 中,将 `Particle Color` 与 `User.Color` 相乘。材质中的 `Emissive Color` 也乘以 `User.Color`,即可实现一键换色。

    进阶建议

    以上流程覆盖了格挡特效的核心逻辑,但如果你想让效果更上一个台阶,可以尝试:
    1. 结合 Chaos 物理:将碎片发射器改为 Chaos 物理资产,让碎片与场景中的其他物体产生真实碰撞(如击飞花瓶、弹开小石子)。
    2. 音效同步:在 Niagara 的 `Particle Event` 中触发 `Play Sound at Location`,让碰撞声、碎片落地声与粒子同步。
    3. 后处理联动:在碰撞瞬间激活一个 `Post Process Material`,添加径向模糊或色差效果,增强冲击感。

    最后提醒:制作特效时,多观察现实中的物理现象——比如水花溅开的形状、玻璃破碎的碎片分布。把这些观察结果转化为 Niagara 中的数学参数,你的特效就会拥有“灵魂”。

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