UE5 魔法阵特效制作:用 Niagara 和材质实现动态符文
上周刚结束的进阶班答疑课上,有位学员举着《原神》里芭芭拉的水环问我:“老师,这种脚下魔法阵,用贴图旋转做出来总是发虚,边缘锯齿也明显,有没有办法让它像游戏里那样有能量流动感?” 这个问题很有代表性。大多数入门教程会教你用一张 `T_Radial_Gradient` 贴图配合 `Panner` 节点做无限循环滚动,但那种做法有两个硬伤:一是UV平铺导致边缘接缝明显,二是只能做整体旋转,无法实现符文独立旋转、缩放、浮现等动态效果。今天这篇文章,我们就用 UE5.3 的 Niagara 粒子系统配合材质函数,从零搭建一个可复用的动态魔法阵资产。全程不涉及蓝图,纯材质与粒子配合,你能直接拿到项目里用。
一、材质基础:用 Custom 节点生成程序化符文
我们先解决“边缘发虚”和“符文动态”这两个核心痛点。传统贴图方案的瓶颈在于纹理分辨率固定,放大必糊。而程序化生成则完全不受分辨率限制,且每个符文都可以独立控制。
步骤 1:创建材质函数 MF_RuneShape
在 Content Browser 中右键 → `Materials & Textures` → `Material Function`,命名为 `MF_RuneShape`。打开后,我们用一个 `Custom` 节点写 GLSL 代码来生成符文轮廓。双击 Custom 节点,在 Code 框输入:
float angle = atan2(LocalPosition.y, LocalPosition.x);
float radius = length(LocalPosition);
float runeMask = 0.0;// 主圆环
runeMask += smoothstep(0.9, 0.85, radius) * (1.0 - smoothstep(1.0, 0.95, radius));
// 六芒星(两个三角形叠加)
float tri1 = step(0.5, abs(sin(angle * 3.0 + 0.5)));
float tri2 = step(0.5, abs(sin(angle * 3.0 - 0.5)));
runeMask += (tri1 tri2) smoothstep(0.4, 0.35, radius);
// 外圈符文点阵(8个圆点)
float dotAngle = floor(angle / (2.0 3.14159 / 8.0)) (2.0 * 3.14159 / 8.0);
float dotDist = length(LocalPosition - float2(cos(dotAngle), sin(dotAngle)) * 1.2);
runeMask += smoothstep(0.1, 0.08, dotDist);
return runeMask;
这里 `LocalPosition` 是材质函数内部默认提供的局部坐标,范围 -1 到 1。`smoothstep` 用于抗锯齿边缘,`atan2` 计算角度,`floor` 做环形阵列。把这个函数的 `Material Function Output` 连到 Emissive Color。
步骤 2:主材质设置
新建材质 `M_MagicCircle`,材质域设为 `Deferred Decal`(延迟贴花),混合模式 `Translucent`,着色模型 `Unlit`。这样魔法阵可以贴在任何表面(地面、墙壁甚至��色身上)。把 `MF_RuneShape` 拖入,并乘上一个 `VectorParameter` 控制颜色。关键参数:
- `Emissive Color`:`(RuneColor * 2.0)` 让亮度超过1,产生HDR辉光
此时你按下 `Apply`,在视口里拖一个 Decal 组件,已经能看到静态的符文圆环。但这是死的,我们需要让符文动起来。
二、Niagara 粒子驱动:让符文旋转、缩放、浮现
Niagara 在这里不是用来生成粒子,而是作为“动态参数驱动器”。我们创建一个 Niagara 系统,它不发射可见粒子,而是通过 `Particle Attribute Reader` 把每帧的旋转角度、缩放比例传给材质。
步骤 3:创建 Niagara 系统
在 Content Browser 右键 → `FX` → `Niagara System`,选择 `New system from a template`,选 `Empty`。打开后:
1. 在 `Emitter Update` 中添加 `Spawn Rate`,设为 1(每帧更新一次)
2. 添加 `Particle State`,设置 `Life Cycle` 为 `Infinite`(无限循环)
3. 在 `Particle Spawn` 中添加 `Set Variables`:初始化 `RuneAngle` = 0.0,`RuneScale` = 1.0
4. ��� `Particle Update` 中添加 `Add Float`:`RuneAngle += DeltaTime * 30.0`(每秒旋转30度)
5. 再添加 `Sine` 表达式:`RuneScale = 0.8 + 0.2 sin(DeltaTime 2.0)`(呼吸缩放效果)
步骤 4:通过 Renderer 传递参数到材质
在 Niagara 的 `Renderer` 中,选择 `Light Renderer`(不显示网格体)或直接留空。关键在 `Material Binding`:
回到材质 `M_MagicCircle`,添加两个 `ScalarParameter`:`AngleParam`(默认0)和 `ScaleParam`(默认1)。在 `MF_RuneShape` 中,把 `LocalPosition` 乘上 `ScaleParam`,再把整个坐标旋转 `AngleParam`:
float2 rotatedPos = float2(
LocalPosition.x cos(AngleParam) - LocalPosition.y sin(AngleParam),
LocalPosition.x sin(AngleParam) + LocalPosition.y cos(AngleParam)
) / ScaleParam;
注意要除以 ScaleParam 而不是乘,这样缩放是中心向外扩散的视觉。重新编译材质,把 Niagara 系统拖入场景,你会看到魔法阵开始整体旋转并呼吸缩放。
三、进阶:多符文独立控制与流动能量
上面的效果还比较单调。真正高级的魔法阵,每个符文应该有自己的节奏。我们扩展 Niagara 系统,使用 `Particle Attribute Reader` 和 `Index` 来区分不同符文。
步骤 5:多粒子系统分层
创建三个 Niagara Emitter(分别命名 `OuterRing`、`InnerRing`、`CenterCore`),每个 Emitter 独立控制。以 `OuterRing` 为例:
材质端,我们改用 `TextureCoordinate` 的 `TexCoord` 数组传递多组参数。在 Niagara Renderer 中,绑定 `TexCoord` 为 `(Angle, Scale)`,材质里用 `TextureCoordinate` 节点分别提取 R 通道和 G 通道作为角度和缩放。
步骤 6:流动能量线
在材质中,我们加一条螺旋线。修改 `MF_RuneShape` 的代码,增加:
float spiral = smoothstep(0.8, 0.6, abs(frac(angle / (2.0 3.14159) + Time 0.5) - 0.5));
runeMask += spiral smoothstep(0.7, 0.5, radius) 0.5;
这里的 `Time` 是材质内置节点 `Time`(需要勾选 `Used Time` 或通过 `Time` 节点传入)。这样会有一条从中心向外旋转的亮线,类似能量汇聚。
最终效果是:外圈8个符文点以不同速度旋转,中圈六芒星呼吸缩放,内圈螺旋能量线顺时针流动,整体再叠加一层慢速旋转。所有参数都由 Niagara 实时驱动,不消耗贴图内存,分辨率无限。
常见问题 FAQ
Q1:为什么我的 Decal 材质显示全黑?
检查 `Deferred Decal` 是否勾选了 `Decal Response` 中的 `Color` 和 `Normal`。另外,确保材质是 `Unlit` 且 `Emissive Color` 大于1,否则在默认光照下会显得很暗。
Q2:Niagara 参数绑定后材质没反应?
在 Niagara 的 Renderer 中,必须选择一种 Renderer 类型(如 `Light Renderer`),否则参数绑定不会生效。另外,材质参数名要完全一致,包括大小写。
Q3:魔法阵边缘有锯齿?
检查 `smoothstep` 的宽度参数。建议 `smoothstep(0.9, 0.85, radius)` 的第二个值比第一个小0.05左右,这样过渡带约2-3像素,足够抗锯齿。如果还不行,在材质设置中开启 `Temporal AA`。
Q4:如何让魔法阵跟随角色移动?
使用 `Attach Actor` 组件或 `Set World Location` 每帧更新。更高效的方式是使用 Niagara 的 `Local Space` 模拟,勾选 Emitter 的 `Local Space` 后,系统会自动随组件移动。
Q5:性能开销大吗?
程序化材质无贴图采样,Niagara 粒子数极少(最���几十个),整体开销比同分辨率贴图方案低30%左右。但注意不要在移动端使用过多 `Custom` 节点,建议移动端用简化版(减少三角形数量)。
学习建议
这篇文章只是冰山一角。Niagara 真正的威力在于它可以把任何参数(时间、位置、速度)映射到材质,实现“数据驱动特效”。建议你按以下路径深入学习:
1. 先跑通本文案例,然后修改参数观察效果(比如把 `Sine` 改成 `Noise`,看看随机缩放的效果)
2. 研究 `Particle Attribute Reader`,它是 Niagra 与材质通信的桥梁,掌握 `Index` 和 `Tag` 用法
3. 尝试用 `Skeletal Mesh` 的顶点位置驱动粒子,实现角色身体上的魔法纹路
4. 结合 AIGC 工具(如 Stable Diffusion 生成符文贴图素材),用本文程序化方法做动态,两者互补
如果你在练习中遇到问题,欢迎在评论区贴出你的节点截图,我会逐一解答。下期文章我们讲如何用 `Particle Attribute Reader` 实现“粒子沿魔法阵轨迹飞行”的拖尾效果,到时见。

评论(0)