For Loop是让你指定一个整数范围来循环;For Each Loop则是专门用来遍历数组中的每一个元素。
📖 预备知识:认识循环节点
在开始前,先来熟悉下它们的”真面目”:
-
For Loop(指定次数循环):最基础的循环节点。你需要设定一个整数起始值(First Index) 和结束值(Last Index),它就会从起始值循环到结束值。 -
For Loop with Break(可中断的循环):For Loop的升级版,在循环体(Loop Body)中多了一个Break执行引脚。你可以通过逻辑条件触发它来立即终止循环。 -
For Each Loop(遍历数组循环):专门用来遍历数组或集合。它会自动将数组中的每个元素取出,供你在循环体中使用。输出引脚的Array Element是当前遍历到的元素,Array Index是它的索引值。
🏗️ 案例一:在场景中生成一排立方体(For Loop)
假设我们想在游戏开始时,在世界中生成一排间隔200cm的立方体。
-
准备:创建一个
Actor蓝图,命名为BP_CubeSpawner。 -
变量:在其事件图表中,创建一个
Actor类型的变量CubeClass,并设置为可编辑(Editable)。在蓝图细节面板中,将这个变量默认值指定为Basic Cube类(或你准备生成的立方体类)。 -
逻辑搭建:
-
在事件开始运行(Event BeginPlay) 节点后,拖出
For Loop节点。 -
在
For Loop的细节面板或节点引脚上,设置First Index为0,Last Index为4。这意味着循环将执行5次(5 = 4 - 0 + 1),Index值分别为0、1、2、3、4。 -
从
For Loop的Loop Body执行引脚拖出,添加Spawn Actor from Class节点。 -
将
CubeClass变量连接到Spawn Actor from Class节点的Class输入。 -
计算出生位置(关键步骤):
-
添加一个
Vector节点作为出生位置(Spawn Transform 的 Location)。 -
将
For Loop输出的Index整数与一个Float节点(值为200.0)进行乘法运算。现在,位置的计算公式是(Index * 200, 0, 100)。 -
将这个乘法结果连接到
Vector的X轴上,使其沿X轴排开。 -
(可选) 也可以将Y或Z轴连接此值,改变排列方向。
-
-
最后,将
For Loop的Completed引脚连接到Print String节点,输出”生成完毕”。
-
搭建完成后,编译并保存BP_CubeSpawner,把它拖入你的游戏关卡。运行时,你会看到一排立方体”唰”地一下沿着X轴方向整齐地生成出来。
(提示:你可以在这个位置计算公式上做更多尝试,比如Vector(Index * 200, Index * 100, 0)就能生成一个斜向的、类似楼梯的排列效果。)
🎯 案例二:遍历玩家背包并打印物品(For Each Loop)
我们现在想实现一个”打印背包”的功能,在游戏中,按下某个按键就能将背包数组中的所有物品名称打印到屏幕上。
-
变量准备:
-
创建一个
Actor蓝图。 -
在事件图表中,创建变量,类型选择
Array,然后选择String(字符串)作为元素类型,命名为ItemList。编译蓝图后,将ItemList变量的默认值设为几件物品,例如 “Health Potion”, “Mana Potion”, “Sword”。
-
-
输入逻辑:
-
从事件开始运行(Event BeginPlay) 拉出引脚,添加
Input Action事件(例如IA_PrintInventory)。如果UI栏没有这个事件节点,在事件图表中右键输入”Input Action”搜索。 -
在
IA_PrintInventory的执行输出引脚(>),拖出For Each Loop节点。
-
-
遍历打印:
-
将变量
ItemList(从左侧变量栏拖出) 连接到For Each Loop节点的Array输入。 -
从
Loop Body执行引脚拖出,添加Print String节点。 -
将
For Each Loop输出的Array Element(String类型)连接到Print String节点的In String输入。
-
现在,运行时按下你绑定的打印按键,屏幕日志就会将背包里的物品逐一打印出来。
🛑 案例三:查找并中断(For Loop with Break)
这个案例说明如何在循环过程中,一旦找到目标就提前结束循环,以提升性能。这是我们实现”寻找第一个高级敌人”的逻辑。
-
准备:假设我们有一个
Enemies数组,里面存储着各种敌人,每个敌人都有一个bIsElite(布尔值) 的变量来标识是否为精英。 -
逻辑搭建:
-
在事件图表中创建一个
For Loop with Break节点。 -
将
Enemies数组的长度(Length)节点的返回值连接到Last Index。将First Index设置为0。 -
从
Loop Body执行引脚拖出逻辑:使用Get (a copy)节点,并通过Index输出获取数组中的特定敌人。 -
对获取到的敌人执行
Branch(分支)判断,检查其bIsElite是否为true。-
如果
true:代表找到了精英敌人,执行某些逻辑(如标记焦点目标),然后拉出一条连线连接到For Loop with Break的Break执行引脚,以中断后续所有循环,大幅节省性能。 -
如果
false:继续下一个循环。
-
-
最后,将
Completed引脚连接到Print String节点,输出”未找到精英敌人”。
-
这样,通过Break引脚,我们只遍历到找到的第一个精英敌人就停止,逻辑非常高效。
🧰 高级技巧:嵌套循环与性能优化
-
嵌套循环:
For Loop节点内部可以再放置另一个循环,但这会带来计算量的几何级增长。例如,一个循环100次,内部再循环100次,总执行次数就是10000次,可能导致游戏运行卡顿。 -
单帧卡顿问题:这是使用循环最需注意的性能陷阱。默认情况下,蓝图循环的所有迭代会在同一帧内完成。如果一个循环体计算量过大,或循环次数过多(有测试表明超过25万次),可能会让游戏瞬间”卡死”。
-
破解之道:多帧执行
-
使用Timer:用定时器(Timer) 循环执行
Spawn Actor的逻辑,可以精准控制每次生成的时间间隔。 -
使用’将循环分散到多个Tick’的宏:可以参考UE社区提供的解决方案,通过在每个Tick中只执行一次循环迭代的方式来分摊计算压力。
-
降低循环上限:重新评估你的循环次数。例如,生成1000个敌人或许可以改为按需动态生成。
-
💎 总结:三种循环节点的选择指南
简单总结一下,帮你快速做出选择:
| 需求场景 | 推荐使用的节点 | 核心优势 |
|---|---|---|
| 知道循环多少次 (例如,精确生成5排障碍物) | For Loop |
逻辑简洁高效,最适合固定次数循环。 |
| 遍历并操作整个数组 (例如,重置背包所有物品) | For Each Loop |
代码更直观,不需要手动管理索引。 |
| 遍历并搜索数组中的特定元素 (例如,找到第一个钥匙并打开门) | For Each Loop with Break 或 For Loop with Break |
提供Break功能,找到目标后立即停止,性能最佳。 |
💡 专业提示:如果你的逻辑是在每一帧(Event Tick) 中运行的,请绝对避免使用任何循环节点,这是导致游戏运行效率低下的常见原因。
🎓 学习路径建议
要彻底掌握For Loop,建议按以下顺序实践:
-
理解机制:光看不够。打开UE5编辑器,自己动手创建几个
For Loop,打印Index值来观察它的运行顺序。 -
实际场景结合:将
For Loop放入复杂逻辑中,例如:-
在一个”武器升级系统“中,用
For Loop来计算每次升级所需的累计经验值。 -
在一个”可破坏物系统“中,用
For Loop``一次性生成大量碎片,并用For Loop with Break`来快速找到摧毁效果。
-
-
故障排除参考:
-
如果在循环内需要等待几秒后再执行下一步(比如每次生成敌人有间隔),
Delay节点无法正常工作。你应该改用定时器(Timer)。 -
如果在调试时发现
Breakpoint(断点)只触发一次,这是UE引擎的一个已知界面问题,不影响实际逻辑,继续调试即可。
-
掌握循环,就是掌握了驾驭重复逻辑的钥匙。它将是构建复杂游戏机制时最得力的助手。
感谢您的来访,获取更多精彩文章请收藏本站。







暂无评论内容