路徑探索 是將角色移動到邏輯路徑上以達到目的地的過程,避免障礙物和(可選)危險材料或定義區域。
導航可視化
為了幫助路徑檢索佈局和偵錯,Studio 可以渲染一個導航網格和 修改器 標籤。要啟用它們,請在3D視角右上角的視覺選擇選項控件中切換 導航網格 和 路徑修改器 ,以啟用它們。

啟用 導航網格 後,彩色區域會顯示角色可能走路或游泳的地方,而非彩色區域被阻止。小箭頭表示角色將透過跳躍嘗試到達的區域,假設你在 AgentCanJump 時設置 true 為 。

啟用了 路徑檢索修改器 ,文字標籤指示了在使用 路徑檢索修改器 時考慮的特定材料和區域。

已知限制
路徑探索功能具有特定限制,以確保高效處理和最佳效履約。
垂直放置限制
路徑檢索計算只考慮特定垂直邊界內的零件:
- 下限 — 具有底部 Y 坐標小於 -65,536 個單位的零件被忽略。
- 上限 — 擁有最高 Y 坐標的零件超過 65,536 個螺柱的零件被忽略。
- 垂直距離 — 從最低部分底 Y 坐標到最高部分頂 Y 坐標的垂直距離不得超過 65,536 個單位;否則,路徑檢索系統在路徑檢索計算過程中將忽略這些部分。
搜尋距離限制
從起點到終點的路徑尋找直接視線距離不得超過 3,000 個單位。超過此距離會導致NoPath狀態。
建立路徑
路徑探索通過 PathfindingService 和其 CreatePath() 功能來啟動。
本地脚本
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath()
CreatePath() 接受可選的參數表,可調整角色 (代理) 在路徑上移動的方式。
關鍵 | 說明 | 類型 | 預設 |
---|---|---|---|
AgentRadius | 代理範圍,以點為單位。用於確定最小與障礙物的分離。 | 整數 | 2 |
AgentHeight | 代理高度,以厘米為單位。小於此值的空間,例如樓梯下的空間,將被標為無法穿越。 | 整數 | 5 |
AgentCanJump | 決定是否允許在路徑探索期間跳躍。 | boolean | true |
AgentCanClimb | 決定是否允許在路徑尋找期間攀登TrussParts。 | boolean | false |
WaypointSpacing | 路徑中的中間路點間距離。如果設為 math.huge,將沒有中間路點。 | 數字 | 4 |
Costs | 材料表或定義的PathfindingModifiers和其通過費用。有助於讓代理偏愛某些材料/區域,而不是其他材料/區域。見 修改器 了解詳情。 | 表 | nil |
本地脚本
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath({AgentRadius = 3,AgentHeight = 6,AgentCanJump = false,Costs = {Water = 20}})
請注意,代理在路徑檢索期間可以攀爬 ,假設您將 設為 時創建路徑,並且沒有任何東西阻止代理從桁架攀爬路徑。攀爬路徑具有 攀爬 標籤,攀爬路徑的 費用 為預設值為 1 。

本地腳本 - 桁架攀登路徑
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath({AgentCanClimb = true,Costs = {Climb = 2 -- 攀登路的費用;默認值為 1}})
沿路移動
此部分使用以下路徑尋找腳本對玩家的角色。要在閱讀時測試:
- 將代碼複製到 LocalScript 內的 StarterCharacterScripts 中。
- 將 TEST_DESTINATION 變數設為玩家角色可以到達的3D世界中的Vector3目標。
- 通過以下部分瞭解路徑計算和角色移動。
本地腳本 - 角色路徑檢索
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
local path = PathfindingService:CreatePath()
local player = Players.LocalPlayer
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local TEST_DESTINATION = Vector3.new(100, 0, 100)
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local function followPath(destination)
-- 計算路徑
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- 取得路徑點
waypoints = path:GetWaypoints()
-- 偵測路徑是否被阻塞
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- 檢查障礙物是否在路徑下方
if blockedWaypointIndex >= nextWaypointIndex then
-- 直到路徑重新計算為止停止偵測路徑阻塞
blockedConnection:Disconnect()
-- 呼叫功能重新計算新路徑
followPath(destination)
end
end)
-- 偵測當前移動到下一個路點完成時
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- 增加路點索引並移動到下一個路點
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- 初始移動到第二個路點 (第一個路點是路徑開啟動;跳過它)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
followPath(TEST_DESTINATION)
計算路徑
在您創建有效路徑 CreatePath() 之後,必須由 計算 通過呼叫 Path:ComputeAsync() 來計算起點和目的地的 Vector3 。
本地腳本 - 角色路徑檢索
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
local path = PathfindingService:CreatePath()
local player = Players.LocalPlayer
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local TEST_DESTINATION = Vector3.new(100, 0, 100)
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local function followPath(destination)
-- 計算路徑
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
end

取得路點
一旦 Path 被計算,它將包含一系列 路徑點 ,用於追蹤從開始到結束的路徑。這些點可以使用 Path:GetWaypoints() 函數收集。
本地腳本 - 角色路徑檢索
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
local path = PathfindingService:CreatePath()
local player = Players.LocalPlayer
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local TEST_DESTINATION = Vector3.new(100, 0, 100)
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local function followPath(destination)
-- 計算路徑
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- 取得路徑點
waypoints = path:GetWaypoints()
end
end

路徑移動
每個路點包括一個 位置 ( Vector3 ) 和一個 行動 ( PathWaypointAction )。若要移動包含 Humanoid 的角色,例如典型 Roblox 角色,最簡單的方法是從路徑到路徑呼叫 Humanoid:MoveTo() ,使用 MoveToFinished 事件偵測角色何時到達每個路徑點。
本地腳本 - 角色路徑檢索
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
local path = PathfindingService:CreatePath()
local player = Players.LocalPlayer
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local TEST_DESTINATION = Vector3.new(100, 0, 100)
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local function followPath(destination)
-- 計算路徑
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- 取得路徑點
waypoints = path:GetWaypoints()
-- 偵測路徑是否被阻塞
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- 檢查障礙物是否在路徑下方
if blockedWaypointIndex >= nextWaypointIndex then
-- 直到路徑重新計算為止停止偵測路徑阻塞
blockedConnection:Disconnect()
-- 呼叫功能重新計算新路徑
followPath(destination)
end
end)
-- 偵測當前移動到下一個路點完成時
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- 增加路點索引並移動到下一個路點
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- 初始移動到第二個路點 (第一個路點是路徑開啟動;跳過它)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
處理被阻止的路徑
許多 Roblox 世界是動態的;零件可能移動或掉落,地板可能崩潰。這可以阻止計算出的路徑並防止角色達到目的地。為了處理這個問題,您可以連接 Path.Blocked 事件並重新計算阻止它的路徑。
本地腳本 - 角色路徑檢索
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
local path = PathfindingService:CreatePath()
local player = Players.LocalPlayer
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local TEST_DESTINATION = Vector3.new(100, 0, 100)
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local function followPath(destination)
-- 計算路徑
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- 取得路徑點
waypoints = path:GetWaypoints()
-- 偵測路徑是否被阻塞
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- 檢查障礙物是否在路徑下方
if blockedWaypointIndex >= nextWaypointIndex then
-- 直到路徑重新計算為止停止偵測路徑阻塞
blockedConnection:Disconnect()
-- 呼叫功能重新計算新路徑
followPath(destination)
end
end)
end
end
路徑探索修改器
預設情況下,Path:ComputeAsync() 返回起點與目的地之間的 最短路徑 ,除了它嘗試避免跳躍之外。在某些情況下,這看起來不自然——例個體、實例,一條路可能會穿過水而不是穿過附近的橋,只因為穿過水的路徑更短。

為了進一步優化路徑檢索,您可以實現 路徑檢索修改器 來計算更聰明的路徑通過各種 材料、區域 或通過 障礙物 。
設定材料成本
當使用 Terrain 和 BasePart 材料時,您可以在 Costs 內包含一個 CreatePath() 表,以使某些材料比其他材料更容易通過。所有材料的默认成本為 1 ,任何材料都可以通過設置其值為 math.huge 來定義為不可穿越。
在 Costs 表中的鑰匙應該是代表 Enum.Material 名稱的字串名稱,例如 Water 對於 Enum.Material.Water .
本地腳本 - 角色路徑檢索
local PathfindingService = game:GetService("PathfindingService")local Players = game:GetService("Players")local RunService = game:GetService("RunService")local Workspace = game:GetService("Workspace")local path = PathfindingService:CreatePath({Costs = {Water = 20,Mud = 5,Neon = math.huge}})
與區域工作
在某些情況下,材料偏好不足以滿足需求。例如,您可能希望角色避免 定義的區域 ,無論是否有材料在腳下。這可以通過將 PathfindingModifier 對象添加到零件來實現。
在危險區域周圍創建一個 Anchored 零件,將其 CanCollide 屬性設置為 false 。
將 PathfindingModifier 實例插入零件,找到其 Label 屬性,並指派意義있的名稱,例如 危險區 。
包含包含匹配鑰匙和相關數值的 Costs 表在 CreatePath() 內,包含匹配的鑰匙和相關的數值。修改器可以通過將值設為 math.huge 來定義為不可檢查的。
本地腳本 - 角色路徑檢索local PathfindingService = game:GetService("PathfindingService")local Players = game:GetService("Players")local RunService = game:GetService("RunService")local Workspace = game:GetService("Workspace")local path = PathfindingService:CreatePath({Costs = {DangerZone = math.huge}})
忽略障礙
在某些情況下,通過路徑找到固體障礙,好像它們不存在。這讓您計算特定物理障礙的路徑,而不是計算完全失敗。
在對象周圍創建一個 Anchored 零件,並將其 CanCollide 屬性設置為 false 。
插入 PathfindingModifier 實例到零件上,啟用其 PassThrough 屬性。
現在,當從殭屍 NPC 到玩家角色的路徑計算出來時,路徑會超出門,您可以提示殭屍穿過它。即使殭屍無法開啟門,它也會反應像是「聽到」門後面的角色。
路徑探索鏈接
有時候需要找到一條通往無法正常穿越的空間的路徑,例如穿越峽谷,並執行自訂行動來到達下一個路點。這可以通過 PathfindingLink 物件來實現。
使用上面的島嶼示例,您可以讓代理使用船而不是步行橫越所有橋樑。

要使用此範例創建 PathfindingLink :
要協助進行視覺化和偵錯,請在 3D 視角右上角的 視覺選項 控件中切換 路徑檢索鏈接 ,以協助進行視覺化和偵錯。
創建兩個 Attachments , 一個在船的座位上, 一個在船的降落點附近。
為其 Label 屬性指派一個有意義的名稱,例如 UseBoat 。此名稱在路徑檢索腳本中用作旗幟,當代理達到起始鏈接點時,觸發自定義行動。
包含 Costs 表中的 CreatePath() 包含 both a Water 鑰匙和一個匹配 Label 屬性名稱的自定义鑰匙的表,包含 both a 鑰匙和一個匹配 屬性名稱的自定义鑰匙的表。為自訂鍵指定值低於 Water 的值。
本地腳本 - 角色路徑檢索local PathfindingService = game:GetService("PathfindingService")local Players = game:GetService("Players")local RunService = game:GetService("RunService")local Workspace = game:GetService("Workspace")local path = PathfindingService:CreatePath({Costs = {Water = 20,UseBoat = 1}})當達到路徑時發生事件時,添加自訂檢查對 Label 修改器名稱的檢查,並執行與 Humanoid:MoveTo() 不同的行動—在這種情況下,呼叫一個函數將代理安裝在船上,移動船隻到水上,然後在到達目的地島時繼續代理的路徑。
本地腳本 - 角色路徑檢索local PathfindingService = game:GetService("PathfindingService")local Players = game:GetService("Players")local RunService = game:GetService("RunService")local Workspace = game:GetService("Workspace")local path = PathfindingService:CreatePath({Costs = {Water = 20,UseBoat = 1}})local player = Players.LocalPlayerlocal character = player.Characterlocal humanoid = character:WaitForChild("Humanoid")local TEST_DESTINATION = Vector3.new(228.9, 17.8, 292.5)local waypointslocal nextWaypointIndexlocal reachedConnectionlocal blockedConnectionlocal function followPath(destination)-- 計算路徑local success, errorMessage = pcall(function()path:ComputeAsync(character.PrimaryPart.Position, destination)end)if success and path.Status == Enum.PathStatus.Success then-- 取得路徑點waypoints = path:GetWaypoints()-- 偵測路徑是否被阻塞blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)-- 檢查障礙物是否在路徑下方if blockedWaypointIndex >= nextWaypointIndex then-- 直到路徑重新計算為止停止偵測路徑阻塞blockedConnection:Disconnect()-- 呼叫功能重新計算新路徑followPath(destination)endend)-- 偵測當前移動到下一個路點完成時if not reachedConnection thenreachedConnection = humanoid.MoveToFinished:Connect(function(reached)if reached and nextWaypointIndex < #waypoints then-- 增加路點索引並移動到下一個路點nextWaypointIndex += 1-- 如果路徑標籤是「使用船」,則使用船;否則前往下一個路徑if waypoints[nextWaypointIndex].Label == "UseBoat" thenuseBoat()elsehumanoid:MoveTo(waypoints[nextWaypointIndex].Position)endelsereachedConnection:Disconnect()blockedConnection:Disconnect()endend)end-- 初始移動到第二個路點 (第一個路點是路徑開啟動;跳過它)nextWaypointIndex = 2humanoid:MoveTo(waypoints[nextWaypointIndex].Position)elsewarn("Path not computed!", errorMessage)endendfunction useBoat()local boat = Workspace.BoatModelhumanoid.Seated:Connect(function()-- 如果代理座位,開始船移動if humanoid.Sit thentask.wait(1)boat.CylindricalConstraint.Velocity = 5end-- 偵測島與約束位置的關係local boatPositionConnectionboatPositionConnection = RunService.PostSimulation:Connect(function()-- 在島嶼旁停止船隻if boat.CylindricalConstraint.CurrentPosition >= 94 thenboatPositionConnection:Disconnect()boat.CylindricalConstraint.Velocity = 0task.wait(1)-- 取消座位代理並繼續前往目的地humanoid.Sit = falsehumanoid:MoveTo(waypoints[nextWaypointIndex].Position)endend)end)endfollowPath(TEST_DESTINATION)
傳輸兼容性
體驗內的 實例傳輸 是一個強大的功能,可以動態載入和卸載 3D 內容,當玩家的角色在世界上移動時。隨著他們探索 3D 空間,新的子空間流到他們的設備,並且一些現有的子空間可能會流出。
考慮使用 PathfindingService 在啟用傳輸的體驗中的以下最佳做法:
傳輸可以阻止或解除給定路徑上的角色移動時。例如,當角色通過森林時,一棵樹可能會在他們前方的某處流入並阻礙道路。為了使路徑尋找與串流無縫運作,建議您使用 處理阻塞路徑 技術,並在必要時重新計算路徑。
在路徑探索中的一個常見方法是使用現有對象的坐標進行 計算,例如將路徑目的地設置為世界上現有 寶箱模型 模型的位置。這種方法與服務器側的 Scripts 完全相容,因為服務器隨時都有世界的完整視圖,但 LocalScripts 和 ModuleScripts 在客戶端運行的可能會失敗,如果他們嘗試計算一個對象的路徑,該對象並未在輸入中流式傳輸。
為了解決這個問題,請考慮將目的地設置為永久模型中的 位置。永久模型會在玩家加入後不久載入,它們永遠不會流出,因此客戶端腳本可以連接到 PersistentLoaded 事件並安全地存取模型,創建路徑點後事件發生時。