UE5 魔法阵特效制作:用 Niagara 和材质实现动态符文

上周刚结束的进阶班上,一位学员拿着他做的“魔法阵”跑来问我:“老师,为什么我的阵看起来像贴了张彩色玻璃纸?既没有能量涌动的感觉,符文也死气沉沉的。” 我看了眼他的工程文件——材质里只用了自发光颜色,Niagara 粒子只是在平面上随机飘。问题很典型:他试图用“贴图”去模拟“能量”,而不是用“规则”去生成“动态”

真正的魔法阵特效,核心在于“符文”的脉动节奏与“能量流”的指向性。今天这篇教程,我们就用 UE5.3 版本(5.2+ 均适用)的 Niagara 和材质系统,从零搭建一个可复用的动态符文法阵。你将学到如何用材质函数生成旋转符文,以及如何用 Niagara 的 `Sample Position` 和 `Mesh Renderer` 让能量环真正“活”过来。

一、材质篇:用 Custom 节点写一个旋转符文核心

很多教程教你用 Photoshop 画一张符文贴图,但那是静态的。我们要做的符文,它的每一笔都应该是“活”的——旋转、缩放、明暗呼吸。这里我们用材质编辑器里的 Custom 节点 写一段 HLSL 代码,直接生成符文图案。

步骤 1:创建基础材质

1. 在 Content Browser 右键 → Material,命名为 `M_Rune_Core`。
2. 打开材质,将 Blend Mode 设为 Additive(加法混合),Shading Model 设为 Unlit(无光照)。
3. 添加一个 Custom 节点(快捷键 C),连接至 Emissive Color。

步骤 2:编写符文生成代码

双击 Custom 节点,粘贴以下代码(这是极坐标下基于角度和半径的条纹干扰):

// 输入UV: 0-1范围
float2 uv = UV * 2.0 - 1.0; // 中心化
float r = length(uv);
float theta = atan2(uv.y, uv.x) + ROTATION_SPEED * Time; // 旋转

// 符文主体:基于角度分割的线条 float rune = 0.0; // 主环 rune += smoothstep(0.7, 0.65, r) (0.5 + 0.5 sin(theta 8.0 + Time 2.0)); // 内圈符文点阵 rune += smoothstep(0.45, 0.4, r) (0.5 + 0.5 sin(floor(theta 12.0) 3.14159 2.0 + Time 3.0)); // 中心亮点 rune += exp(-r 8.0) (0.8 + 0.2 sin(Time 5.0));

return rune * Intensity;

步骤 3:设置参数

在 Custom 节点右侧添加三个 Scalar Parameter:`ROTATION_SPEED`(默认 0.5)、`Time`(默认 0)、`Intensity`(默认 3.0)。其中 `Time` 需要在材质蓝图中用 Time 节点(快捷键 T)驱动。

步骤 4:应用与测试

将材质赋予一个平面(Plane)或圆环(Torus),旋转一下视角。你会看到符文在自转,且边缘有粒子般的闪烁。如果觉得线条太硬,可以在 `smoothstep` 的第二个参数上做文章,比如改成 `smoothstep(0.7, 0.62, r)` 让边缘更柔和。

> 进阶技巧:把 `theta 8.0` 改成 `theta 16.0`,符文会变成 16 瓣。配合 `Time` 的缩放,可以实现“符文从中心向外扩展”的效果。

二、Niagara 篇:让能量环沿法线流动

材质解决了“符文长什么样”,Niagara 解决“能量怎么动”。我们要做一个沿着法线方向(垂直平面向外)喷射的粒子环,并让粒子颜色与材质呼应。

步骤 1:创建 Niagara 系统

1. 右键 → FXNiagara System,选择 New system from a template,选 Empty
2. 在 Emitter 上右键 → Add EmitterEmpty。命名为 `E_Ring_Flow`。

步骤 2:设置粒子生命周期与位置

Emitter Update 中:

  • 添加 Spawn Rate,设为 200(每秒 200 个粒子)。
  • 添加 Initialize Particle,将 Lifetime 设为 0.8~1.2(随机)。
  • Particle Spawn 中:

  • 添加 Set Position,使用 User.ArrayGrid Location。这里我们用 Random Unit Vector 乘以半径 100,得到一个圆环上的随机点。
  • 关键一步:添加 Set Velocity,方向设为 `Normalize(Position)` * 向外喷射速度(如 200)。这样粒子会沿径向飞散。
  • 步骤 3:让粒子沿法线“呼吸”

    我们不希望粒子一直飞,而是希望它们像波纹一样起伏。在 Particle Update 中:

  • 添加 Scale Sprite Size,设为 `0.5 + 0.5 sin(Time 5.0 + NormalizedAge * 6.28)`。
  • 添加 Set Color,使用 CurveColor Over Life。建议初段亮白,中段偏蓝紫,末段透明。
  • 步骤 4:使用 Mesh Renderer 替代 Sprite

    Sprite 太扁平,我们用 Mesh Renderer
    1. 在 Render 模块中选择 Mesh Renderer
    2. 将 Mesh 设为引擎自带的 `Cylinder`(圆柱体),并设置缩放为 `(0.2, 0.2, 1.0)`。
    3. 在 Material 中指定我们之前创建的 `M_Rune_Core` 材质。

    这样,每个粒子都是一个微小的圆柱体,沿法线方向排列,整体看起来就像能量流在符文表面流动。

    步骤 5:添加辅助力场

    为了让效果更“魔法”,在 Emitter Update 中添加 Turbulence Force,强度设为 50,频率设为 0.3。这会让粒子有微弱的扰动,避免过于机械。

    三、整合与优化:让法阵融入场景

    现在你有两个元素:一个静态符文平面(材质),一个粒子环(Niagara)。但要让它们“合一”,需要做两件事:

    1. 材质接收粒子数据

    在 `M_Rune_Core` 材质中,添加一个 Particle Color 节点,与 Emissive Color 相乘。这样粒子环的颜色变化会影响符文本身的亮度,实现“共振”效果。

    2. 用 Niagara 驱动材质参数

    我们可以在 Niagara 系统中添加一个 User.Exposed 变量(如 `User.RuneIntensity`),然后在材质蓝图里通过 Niagara User Parameter 节点读取它。例如,当粒子爆发时,`RuneIntensity` 升高,符文变亮。

    3. 性能优化

  • 粒子数量:200 足够,不要超过 500。
  • 材质复杂度:Custom 节点计算量小,但避免在材质里用 `TextureSample` 做高频噪声。
  • 使用 Fixed Bounds 来减少 Niagara 的包围盒计算。
  • 实际效果测试:把一个 Point Light 放在法阵中心,颜色调成偏蓝(如 `(0.2, 0.4, 1.0)`),强度调为 5000。你会发现粒子环和符文会因光照而更有层次。

    四、总结与进阶建议

    今天我们做了两件事:用材质 Custom 节点生成了动态旋转符文,用 Niagara 的 Mesh Renderer + 径向速度做出了能量流。这个组合可以复用到任何“圆形法阵”场景,比如传送门、召唤仪式、技能释放。

    进阶方向
    1. 用 Distance FieldSDF 让符文在空间上真正“浮空”,而不是贴在地面。
    2. 在 Niagara 里读取 骨骼网格体 的顶点位置,让法阵贴合角色手掌或地面坡度。
    3. 结合 Audio Spectrum 让符文随音乐节奏脉冲(Niagara 支持 `Audio Spectrum` 数据源)。

    如果你想要更炫酷的“符文从地面升起”效果,可以试试在材质里用 `World Position Offset` 让平面在 Y 轴上有波浪形位移,配合 Niagara 的粒子上升。

    常见问题 FAQ

    Q1:为什么我的 Custom 节点代码编译报错?
    A:检查是否所有变量都声明了(如 `ROTATION_SPEED` 需要在节点右侧添加参数并连接到 `Inputs`)。另外,UE 的 HLSL 不支持隐式类型转换,`UV * 2.0 – 1.0` 要确保 UV 是 `float2` 类型。

    Q2:粒子飞得太快,一下就散开了怎么办?
    A:降低 `Set Velocity` 中的速度值,或者给粒子添加 Drag(阻尼)模块,建议设为 0.5~1.0。另外可以增大 `Initialize Particle` 中的 Lifetime,让粒子存活更久。

    Q3:Mesh Renderer 的圆柱体太显眼,看起来像一堆棍子?
    A:将圆柱体的缩放 Z 轴调小(如 0.1),并开启 Mesh Renderer 中的 `Enable Facing`(面向摄像机)。如果还不行,改用 Sprite Renderer 配合 `Circle` 贴图。

    Q4:材质里的 `Time` 节点在 Niagara 驱动时无效?
    A:材质里的 `Time` 节点是全局时间。如果你想让材质受 Niagara 控制,需要将材质参数暴露为 Dynamic Parameter,并在 Niagara 的 Particle Spawn 中通过 `Set Dynamic Material Parameter` 模块来更新。

    Q5:如何让法阵在地面上不穿模?
    A:在 Niagara 的 Initialize Particle 中,将 Y 轴(高度)强制设为 0.5(假设地面在 0 高度),并关闭粒子的重力。如果地面有起伏,可以使用 Scene Query 模块(如 `Collision Query`)来采样地面高度。

    如果你在练习中遇到“粒子不显示”或“材质全黑”这类基础问题,先检查两点:Niagara 的 Renderer 是否启用了 `Visible`,材质的 `Unlit` 和 `Additive` 是否设置正确。动手敲一遍代码,比看十遍教程有用。下次课我们讲怎么把法阵变成“动态技能指示器”,用 Niagara 的 `Neighbor Grid` 做范围预警。下课!

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