虚幻引擎节点 For Loop 介绍

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的立方体。

  1. 准备:创建一个Actor蓝图,命名为 BP_CubeSpawner

  2. 变量:在其事件图表中,创建一个Actor类型的变量 CubeClass,并设置为可编辑(Editable)。在蓝图细节面板中,将这个变量默认值指定为 Basic Cube 类(或你准备生成的立方体类)。

  3. 逻辑搭建

    • 事件开始运行(Event BeginPlay) 节点后,拖出For Loop节点。

    • For Loop的细节面板或节点引脚上,设置 First Index 为 0Last Index 为 4。这意味着循环将执行5次(5 = 4 - 0 + 1),Index值分别为0、1、2、3、4。

    • For LoopLoop 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)

我们现在想实现一个”打印背包”的功能,在游戏中,按下某个按键就能将背包数组中的所有物品名称打印到屏幕上。

  1. 变量准备

    • 创建一个Actor蓝图。

    • 事件图表中,创建变量,类型选择 Array,然后选择String(字符串)作为元素类型,命名为 ItemList。编译蓝图后,将ItemList变量的默认值设为几件物品,例如 “Health Potion”, “Mana Potion”, “Sword”。

  2. 输入逻辑

    • 事件开始运行(Event BeginPlay) 拉出引脚,添加 Input Action 事件(例如 IA_PrintInventory)。如果UI栏没有这个事件节点,在事件图表中右键输入”Input Action”搜索。

    • IA_PrintInventory 的执行输出引脚(>),拖出 For Each Loop 节点。

  3. 遍历打印

    • 将变量 ItemList (从左侧变量栏拖出) 连接到For Each Loop节点的 Array 输入。

    • 从 Loop Body 执行引脚拖出,添加 Print String 节点。

    • For Each Loop输出的 Array Element(String类型)连接到Print String节点的 In String 输入。

现在,运行时按下你绑定的打印按键,屏幕日志就会将背包里的物品逐一打印出来。

🛑 案例三:查找并中断(For Loop with Break)

这个案例说明如何在循环过程中,一旦找到目标就提前结束循环,以提升性能。这是我们实现”寻找第一个高级敌人”的逻辑。

  1. 准备:假设我们有一个 Enemies 数组,里面存储着各种敌人,每个敌人都有一个 bIsElite (布尔值) 的变量来标识是否为精英。

  2. 逻辑搭建

    • 在事件图表中创建一个 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,建议按以下顺序实践:

  1. 理解机制:光看不够。打开UE5编辑器,自己动手创建几个For Loop,打印Index值来观察它的运行顺序。

  2. 实际场景结合:将For Loop放入复杂逻辑中,例如:

    • 在一个”武器升级系统“中,用For Loop来计算每次升级所需的累计经验值。

    • 在一个”可破坏物系统“中,用For Loop``一次性生成大量碎片,并用For Loop with Break`来快速找到摧毁效果。

  3. 故障排除参考

    • 如果在循环内需要等待几秒后再执行下一步(比如每次生成敌人有间隔),Delay节点无法正常工作。你应该改用定时器(Timer)

    • 如果在调试时发现Breakpoint(断点)只触发一次,这是UE引擎的一个已知界面问题,不影响实际逻辑,继续调试即可。

掌握循环,就是掌握了驾驭重复逻辑的钥匙。它将是构建复杂游戏机制时最得力的助手。

感谢您的来访,获取更多精彩文章请收藏本站。

THE END
喜欢就支持一下吧
点赞5 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容