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

上周有位学员问我:“老师,我在项目里想做一个旋转的魔法阵,但用 Sprite 和粒子硬堆,效果又卡又假,有没有更高效的方法?”这个问题很典型。很多刚接触 UE5 特效的同学,习惯用大量精灵图(Sprite)去模拟复杂图案,结果性能爆炸,效果还像“贴图在转圈”。其实,UE5 的 Niagara 系统和材质编辑器,完全可以用程序化方式生成动态符文,既省性能又灵活。

今天,我就带你从零搭建一个可旋转、可脉冲光效的魔法阵。我们会用到 Niagara 6.0(UE5.4 版本)和 材质编辑器,不需要任何外部贴图。全程操作基于 Unreal Engine 5.4.2

一、材质基础:用 Custom Node 绘制符文图案

魔法阵的核心是符文纹理。我们不导入图片,而是用材质中的 Custom HLSL 节点,直接通过数学函数绘制图案。这样做的好处是:分辨率无限、没有模糊、可以实时动画。

步骤 1:创建基础材质

1. 在内容浏览器中右键 → 材质 → 命名为 `M_MagicCircle_Rune`。
2. 打开材质编辑器,将材质域设置为 Surface,着色模型为 Unlit(不需要光照,节约性能)。
3. 创建 Texture Coordinate 节点,输出 UV 坐标。我们需要从 UV 中心计算距离,所以连一个 Append 节点,将 UV 的 U 和 V 分量各自减去 0.5,得到中心化坐标。

步骤 2:用 Distance 函数绘制圆环

1. 创建 Custom 节点,双击打开 HLSL 编辑器,输入以下代码:

float dist = length(UV);
float circle = 1 - step(0.45, dist) * step(dist, 0.48);
return circle;

这段代码的意思是:计算像素到 UV 中心(0.5,0.5)的距离,如果距离在 0.45 到 0.48 之间,则输出 0(黑色),否则输出 1(白色)。这就是一个圆环。

2. 把 Custom 节点的输出连到 Emissive Color 上,并将材质保存。你会看到画面中显示了一个白色圆环。调整 step 函数的阈值可以改变环的粗细。

步骤 3:添加符文图案

圆环太单调了,我们要加入三角形符文。在同一个 Custom 节点里,追加代码:

// 三角形符文:旋转角度为 0, 120, 240 度
float3 pos = float3(UV.x, UV.y, 0);
float angle = atan2(pos.y, pos.x);
// 3 个等分角
float tri = 0;
for (int i = 0; i < 3; i++) {
    float a = angle - (i * 2.094); // 120度 = 2.094 弧度
    // 简单判断:角度在 ±0.3 弧度内,且距离在 0.2-0.4 之间
    if (abs(a) < 0.3 && dist > 0.2 && dist < 0.4) {
        tri = 1;
    }
}
return max(circle, tri);

这里用到了 `atan2` 计算角度,然后循环生成三个等间距的三角形区域。注意:这只是示意代码,实际项目中可以用更复杂的几何函数,比如用 `smoothstep` 做边缘羽化。

材质编辑器中的Custom节点

保存材质后,你会看到一个圆环外加三个三角形符文。如果觉得三角形太锐利,可以用 `smoothstep` 替代 `step` 来过渡。

---

二、Niagara 粒子系统:让符文旋转与脉冲

材质只提供了静态图案,动态效果要靠 Niagara 粒子系统来驱动。我们要实现:整个魔法阵绕 Y 轴旋转,同时符文有呼吸般的脉冲光效。

步骤 1:创建 Niagara 系统

1. 右键 → 特效 → Niagara 系统 → 选择 新建基于模板的 Niagara 系统 → 选 空模板
2. 命名为 `NS_MagicCircle`。
3. 打开 Niagara 编辑器,在 Emitter 属性 中,将 Simulation Target 改为 GPU Compute Sim(GPU 模拟,性能更好)。
4. 添加一个 Sprite 渲染器,并将材质指定为刚才创建的 `M_MagicCircle_Rune`。

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

1. 在 Emitter 更新 模块中添加 Add Velocity,让粒子原地不动(保持位置为 0,0,0)。
2. 添加 Scale Sprite Size,将粒子大小设为 (200, 200, 0) 左右,覆盖屏幕。
3. 关键步骤:添加 Orient Mesh to Camera 并启用 Lock Axis,锁定 Z 轴,这样粒子始终面向相机。

旋转效果不能直接旋转粒子,因为粒子是 Sprite,旋转只会让贴图转。我们需要旋转整个系统的世界坐标。在 System 更新 模块中:

1. 添加 Rotate System 节点,将旋转速度设为 `(0, 30, 0)`,表示每秒绕 Y 轴转 30 度。
2. 为了更自然,添加一个 Sine 函数控制旋转速度的波动:`(0, 30 + 10sin(GetTime() 0.5), 0)`。

步骤 3:实现脉冲光效

脉冲光效需要动态修改材质的参数。我们在材质中预留一个 Scalar Parameter,命名为 `PulseIntensity`,用来控制发光强度。

1. 回到材质 `M_MagicCircle_Rune`,创建一个 Scalar Parameter 节点,命名为 `PulseIntensity`,默认值 1.0。
2. 在 Custom 节点输出前,乘以这个参数:`return max(circle, tri) * PulseIntensity;`。
3. 保存材质。

现在回到 Niagara 系统:

1. 在 粒子更新 模块中添加 Set Parameter,目标选择 ParticleSprite RendererPulseIntensity
2. 将参数值设为 `1.0 + 0.5 sin(GetTime() 3.0)`,这样强度会在 0.5 到 1.5 之间波动,产生呼吸效果。

Niagara参数绑定到材质

运行粒子系统,你会看到魔法阵在旋转,同时符文亮度周期性变化。

---

三、进阶:添加拖尾粒子与动态光线

基础魔法阵已经完成,但视觉上还缺一些“魔法感”。我们再加两个小细节:围绕圆环旋转的拖尾粒子,以及从中心射出的动态光线。

拖尾粒子

在同一个 Niagara 系统中,添加第二个发射器:

1. 右键添加 空发射器,命名为 `TrailEmitter`。
2. 粒子类型改为 Ribbon(带状粒子),渲染器选 Ribbon Renderer
3. 在 粒子生成 中,每帧生成 5 个粒子,生命周期设为 0.5 秒。
4. 粒子位置设为:`(50cos(GetTime()2), 50sin(GetTime()2), 0)`,即沿半径为 50 的圆运动。
5. 粒子大小设为随时间逐渐缩小(从 10 到 0),颜色从蓝色渐变到透明。

这样就会有一条光带绕着圆环旋转,增强动态感。

动态光线(材质实现)

回到材质,在圆环内侧添加一些径向光线。在 Custom 节点中追加代码:

// 径向光线:角度细分 12 条
float radial = 0;
float angle2 = atan2(UV.y, UV.x);
float stepAngle = 3.14159 / 6; // 30度
float nearest = frac(angle2 / stepAngle + 0.5) - 0.5;
float rayWidth = 0.1;
float ray = 1 - smoothstep(0, rayWidth, abs(nearest * stepAngle));
// 只在内圈显示(距离 0.1 到 0.35)
if (dist > 0.1 && dist < 0.35) {
    radial = ray * 0.5;
}
return max(max(circle, tri), radial);

这样圆环内部会出现 12 条辐射状光线,并且会随着整个材质一起旋转。

完成的魔法阵效果

---

总结与进阶建议

通过这个案例,你学会了用 Custom HLSL 在材质中绘制复杂图案,并用 NiagaraSet ParameterRotate System 实现动态控制。这种“材质驱动图案 + 粒子驱动变换”的思路,在 UE5 特效中非常实用,比如制作能量护盾、传送门、技能指示器等。

如果你想让魔法阵更高级,可以尝试:

  • 在 Niagara 中用 Beam 渲染器制作连接符文之间的闪电。
  • Data Interface 读取音频频谱,让符文随音乐跳动。
  • 结合 World Position Offset 让圆环产生波浪形扭曲。
  • 建议你动手复现这个案例,然后试着修改参数,比如改变符文数量、��转速度、脉冲频率,看看能创造出多少变体。特效的本质就是数学与艺术的结合,多调参数多观察,很快你就能做出自己的风格。

    ---

    常见问题 FAQ

    Q1:我按照代码输入了 Custom 节点,但材质显示全黑?
    A:检查 UV 是否中心化。常见错误是直接用了原始 UV(0-1 范围),而代码假设 UV 中心在 0.5。确保用 `Append(UV.x-0.5, UV.y-0.5)` 作为输入。

    Q2:Niagara 粒子旋转时,为什么 Sprite 贴图会变形?
    A:确保 Sprite 渲染器的 Orient Mesh to Camera 已启用,并且 Lock Axis 锁定 Z 轴。如果粒子本身有旋转,会与系统旋转叠加导致扭曲。

    Q3:脉冲参数 PulseIntensity 在 Niagara 中设置后无效?
    A:确认材质参数名称完全一致(区分大小写)。在 Niagara 的 Set Parameter 中,目标选择 ParticleSprite Renderer,然后在参数列表中手动输入参数名。也可以先在材质中编译一次,让参数暴露出来。

    Q4:性能优化方面,这种材质+Niagara 的方案比贴图好在哪里?
    A:贴图需要加载分辨率固定的纹理,且放大后模糊。程序化材质在任意距离都清晰,且只消耗 GPU 的 ALU 运算,不占用显存。Niagara 的 GPU 模拟也比 CPU 粒子更高效。

    Q5:我想让符文在特定时间出现/消失,怎么做?
    A:在材质中添加一个 Scalar Parameter 控制透明度(Opacity Mask),然后在 Niagara 中用 Set Parameter 随时间改变该值。也可以用粒子生命周期来驱动,比如在粒子生成时设置初始值,然后在更新中逐渐减小。

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