Roblox Studio · 第 24 课

自动寻路:让机器人绕过障碍

用 PathfindingService 计算路点,处理跳跃、无路可走和路径被挡住的情况。

10–15 岁 75 分钟 PathfindingService 动手实践 测试与保存

Course overview

机器人看见墙后,能规划一条绕过去的路。

上节课我们亲眼看到,直接朝目标走可能被墙挡住。PathfindingService 会根据可通行区域计算一串路点,再由 Humanoid 逐个走过去。

规划成功和行走成功仍是两件事。墙会移动,路可能被封死,你要让机器人承认失败,而不是一直卡住。

01 · BEFORE

开始之前

完成第 23 课,另存为 Lesson24;禁用旧 Patrol,避免两个脚本同时指挥机器人。

02 · MAKE

你的作品

机器人绕过一面静态墙,走到 Goal;无路或途中被阻挡时安全停止。

03 · CHECK

完成标志

能检查 PathStatus,处理跳跃路点,并在终点输出完成消息。

Studio 显示导航网格的官方截图
图 24-1:官方导航网格截图:可走区域能帮助你发现门太窄、通道断开等场景问题。Roblox Creator Documentation · CC BY 4.0 · 原图未修改 · 许可说明

Learning route

先准备,再动手;看到结果后,记得保存。

每完成一小步,就测试一次。先说出你预计会看到什么,再用 Play 和 Output 检查,不用急着一次写完所有代码。

1

01 · 给机器人留一条真实可走的路

保留 PatrolBot,在前方放一面墙,让左右至少有一侧可以绕行。不要把目标塞进封闭箱子里,然后期待算法穿墙。

2

02 · 先规划,再查看结果

CreatePath 中的 AgentRadius 和 AgentHeight 描述机器人需要的空间。通道太窄,规划器就不应把它当作可通过路线。

3

03 · 依次走路点,必要时跳跃

路点包含 Position 和 Action。Action 为 Jump 时,先让 Humanoid.Jump=true,再走向路点。

4

04 · 看导航网格,不只看漂亮地面

Studio 的可视化选项可以显示 Navigation Mesh。它帮助你观察系统认为哪里能行走,而不是只看模型表面似乎连着。

5

05 · 给无路可走一个明确答案

可靠的机器人不需要每次都成功,但必须让你知道为什么停止。没有可用路径、移动超时和前路被阻挡,都是需要处理的正常情况。

Step by step

01 · 给机器人留一条真实可走的路

保留 PatrolBot,在前方放一面墙,让左右至少有一侧可以绕行。不要把目标塞进封闭箱子里,然后期待算法穿墙。

插入 Goal 路标,并禁用旧 Patrol。相同 Humanoid 同时接收两个脚本的 MoveTo,会让结果难以理解。

  1. Goal:Position=0,0.5,-30,Size=4,1,4,Anchored=true、CanCollide=false。
  2. 墙:Position=0,5,-15,Size=12,10,2,Anchored=true。
  3. 在 ServerScriptService 创建 PathToGoal。
  4. 确认机器人附近地面足够宽,墙两侧有绕行空间。

Step by step

02 · 先规划,再查看结果

CreatePath 中的 AgentRadius 和 AgentHeight 描述机器人需要的空间。通道太窄,规划器就不应把它当作可通过路线。

ComputeAsync 可能出错,因此用 pcall 包住;计算结束后还要检查 path.Status 是否为 Success。pcall 成功只代表调用没抛错,不代表一定有路。

  1. 阅读完整代码中的 ok 与 PathStatus 两层检查。
  2. 用默认比例的 R15 Rig 开始,之后再根据角色尺寸调整参数。

Step by step

03 · 依次走路点,必要时跳跃

路点包含 Position 和 Action。Action 为 Jump 时,先让 Humanoid.Jump=true,再走向路点。

Blocked 只关心当前或后方将要经过的路点。如果前方路线被阻挡,本例停止并提示重新测试;它没有实现动态重新规划,避免把入门课变成追逐 AI。

  1. 把完整代码放进 PathToGoal。
  2. Play 后观察机器人绕过墙,抵达 Goal。
  3. 若失败,先查看 Output,再检查地面、墙边空隙和角色尺寸。
ServerScriptService > PathToGoal · 完整脚本Luau
local PathfindingService = game:GetService("PathfindingService")
local bot = workspace:WaitForChild("PatrolBot")
local humanoid = bot:WaitForChild("Humanoid")
local root = bot:WaitForChild("HumanoidRootPart")
local goal = workspace:WaitForChild("Goal")
root:SetNetworkOwner(nil)
humanoid.WalkSpeed = 8
local path = PathfindingService:CreatePath({
    AgentRadius = 2,
    AgentHeight = 5,
    AgentCanJump = true,
})
local ok, message = pcall(function()
    path:ComputeAsync(root.Position, goal.Position)
end)
if not ok or path.Status ~= Enum.PathStatus.Success then
    warn("No usable path:", message, path.Status.Name)
    return
end

local nextIndex = 2
local blocked = false
local connection = path.Blocked:Connect(function(index)
    if index >= nextIndex then
        blocked = true
        humanoid:MoveTo(root.Position)
    end
end)
local finished = true
local waypoints = path:GetWaypoints()
for index = 2, #waypoints do
    nextIndex = index
    if blocked or humanoid.Health <= 0 then finished = false; break end
    local waypoint = waypoints[index]
    if waypoint.Action == Enum.PathWaypointAction.Jump then humanoid.Jump = true end
    humanoid:MoveTo(waypoint.Position)
    local reached = humanoid.MoveToFinished:Wait()
    if not reached or blocked then finished = false; break end
end
connection:Disconnect()
if finished then print("Reached goal") else warn("Route interrupted; test a new route") end
自动寻路产生的路点可视化截图
图 24-2:官方路点示意图:路径由多个 waypoint 组成。逐个读取路点动作,才能正确处理跳跃。Roblox Creator Documentation · CC BY 4.0 · 原图未修改 · 许可说明

Step by step

04 · 看导航网格,不只看漂亮地面

Studio 的可视化选项可以显示 Navigation Mesh。它帮助你观察系统认为哪里能行走,而不是只看模型表面似乎连着。

图片中的彩色区域和路点属于官方寻路示例。你的墙与 Goal 更简单,但检查方式相同:有没有足够空间绕过去。

  1. 启用导航网格显示,观察墙两侧通路。
  2. 把通道收窄,再计算一次,看结果如何变化。
  3. 完成检查后可关闭网格显示,让场景恢复清楚。

Step by step

05 · 给无路可走一个明确答案

可靠的机器人不需要每次都成功,但必须让你知道为什么停止。没有可用路径、移动超时和前路被阻挡,都是需要处理的正常情况。

本例适合固定小场景。持续追踪移动玩家时,需要节流重算、取消旧任务和处理流式加载,不能简单每帧调用 ComputeAsync。

  1. 开放一侧:应该绕行成功。
  2. 完全封闭目标:应该报告 No usable path。
  3. 恢复空隙:再次 Play 应成功。
  4. 确认结束后 Blocked 连接已经断开。

Homework

轮到你来改一改,做出自己的版本。

1 两条绕行路

分别从墙左侧、右侧留通道,观察路径选择。

2 失败也是结果

记录一次无路可走的测试,截图并说明你怎样修复地图。

3 选做:小台阶

加入可跳的小台阶,观察 Jump 路点;保持下方安全地面。

完成标准:先在 Playtest 中验证作品,再点击 Stop,保存为“姓名缩写_Lesson24”或对应 Homework 副本;不要覆盖上一课的可运行版本。

Exit questions

先自己回答,再展开看看。

pcall 返回 true 就一定找到路了吗?

不是,还要检查 path.Status 是否为 Success。

为什么要看 waypoint.Action?

有些路点需要跳跃,只有 MoveTo 不一定完成动作。

本例会在墙移动后自动重新规划吗?

不会,它会停止并报告。动态重算是更进一步的功能。

为何断开 Blocked 连接?

任务结束后不再需要监听,避免保留过期回调。

Explore further

需要查资料时,从这里出发。

正文代码可以直接复制。先确认脚本类型、放置位置,以及这段代码是完整版本还是小实验;不要把同一脚本的多个版本叠加运行。界面参考图已标注来源,图中的对象名可能与本课不同,请以操作步骤为准。