路徑搜尋 是一個移動角色沿理想路徑到達目的地,避開障礙和 (可選) 危險材料或定義區域。
導航視覺化
要協助確定路徑找路和調試,Studio 可以渲染一個導航網格和 修改器 標籤。要啟用它們,請從 3D 視角上方右邊的 視窗選項 按鈕上的 導航網格 和 2>修改器2> 標籤切換。
啟用 導航網格 時,彩色區域會顯示角色可能走路或游泳的地方,而非彩色區域則會被鎖定。小箭頭指示角色將試著跳躍或游泳的地方,而不是顏色區域。當創建路徑時, AgentCanJump 會自動設置為 true ,假設您將 1>
啟用 路徑找尋模組 時,文字標籤會指示使用 路徑找尋模組 時所考慮的材料和區域。
已知的限制
路徑導航功能有特定限制,以確保有效的處理和最佳性履約。
垂直放置限制
路徑找到計算只考慮特定垂直邊界內的零件:
- 低限制 — 底部 Y 坐標小於 -65,536 格的零件將被忽略。
- 上限 — 超過 65,536 格的零件將被視為無效。
- 垂直距離 — 從最低部分底部 Y 坐標到最高部分 Y 坐標的垂直距離;否則,路徑找索系統會在路徑計算中忽略這些零件。
搜尋範圍限制
從開始到達終點的直線視野距離不得超過 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 和它們的價格為 traversal。 對於使用代理預fer某些材料/區域 over others. 參閱 modifiers 以獲得詳細資訊。 | 表 | nil |
本地指令碼
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath({AgentRadius = 3,AgentHeight = 6,AgentCanJump = false,Costs = {Water = 20}})
注意,代理可以在路徑找到中攀爬 TrussParts 在路徑創建時設定 AgentCanClimb 為 true 當路徑創建時,如果沒有什��
本地指令碼 - 桁架攀爬路徑
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath({AgentCanClimb = true,Costs = {Climb = 2 -- 攀爬路的費用;預設為 1}})
沿路徑移動
此部分使用以下路徑查找指令碼為玩家的角色。要在閱讀時測試:
- 將代碼複製到 LocalScript 內的 StarterCharacterScripts 內。
- 編輯線 11 至 Vector3 玩家角色可以到達的目的地。
- 繼續前進以了解路徑計算和角色移動。
本地指令碼 - 角色路徑找求
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
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
-- 最初移動到第二個 Waypoint (第一個 Waypoint 是路徑開啟動)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
followPath(TEST_DESTINATION)
計算路徑
在您創建有效的路徑使用 CreatePath() 後,它必須是 由計算機呼叫 Class.Path:ComputeAsync() 以及 1> 使用 Datatype.Vector3 作為起始點和目的地點的兩個參數來創建的路徑。
本地指令碼 - 角色路徑找求
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
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 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 ) 和一個 行動 ( 2>Class.Humanoid.MoveTo
本地指令碼 - 角色路徑找求
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
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
-- 最初移動到第二個 Waypoint (第一個 Waypoint 是路徑開啟動)
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 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() 返回最短路線,它與開始點和目的地之間的路線,除了跳過之外,這看起來不自然。在某些情況下, 路線通過水而不是通過附近的橋樑來避免跳躍。
為了進一步優化路徑搜尋,您可以實現 路徑搜尋模組 來計算更聰明的路徑在各種材料、區域和1>障礙1>。
設定材料成本
使用 Terrain 和 BasePart 材料時,您可以包含一個 Costs 表內 1>Class.PathfindingService:CreatePath()|CreatePath()1> 以使某些材料變得比其他材料更可
鍵在 Costs 表中應該是串名代表 Enum.Material 名稱,例如 Water 對於 1> Enum.Material.Water1> 。
本地指令碼 - 角色路徑找求
local PathfindingService = game:GetService("PathfindingService")local Players = game:GetService("Players")local RunService = game:GetService("RunService")local path = PathfindingService:CreatePath({Costs = {Water = 20,Mud = 5,Neon = math.huge}})
與區域作業
在某些情況下,材料偏好 不夠。例如,你可能想要角色避免 定義區域 ,無論是底下的材料。這可以通過添加 Class.Pathfindingmodified 對象到零件來達到此目標。
在危險區域周圍建立一個 Anchored 零件,並將其 CanCollide 屬性設置為 關閉。
將 PathfindingModifier 實例插入零件,找到其 Label 屬性,並且指定一個有意義的名稱,例如 危險區 。
包含 Costs 桌子內的表,其中包含與鑰匙對應的數字值。一個修改器可以由設定其值為 CreatePath() 來定義它不是可交叉的。
本地指令碼 - 角色路徑找求local PathfindingService = game:GetService("PathfindingService")local Players = game:GetService("Players")local RunService = game:GetService("RunService")local path = PathfindingService:CreatePath({Costs = {DangerZone = math.huge}})
忽略障礙
在某些情況下,通過路徑找到通過路徑找到通過路徑不存在的障礙物。這允許您計算通過特定物理方塊的路徑,而不是計算失敗。
在對象周圍創建一個 Anchored 零件,並將其 CanCollide 屬性設置為 關閉 。
將 PathfindingModifier 實例插入零件並啟用其 PassThrough 屬性。
現在,當路徑從殭屍 NPC 至玩家角色時,路徑會從門延伸到外面,並且您可以提示殭屍穿過它。即使殭屍無法打開門,它也會反應像是 "聽"到門後的角色。
路徑查找連結
有時候需要找到一個通過空間無法正常穿越的路徑,例如穿過峭壁,並執行自訂行動來達到下一個方向點。這可以通過 PathfindingLink 物件來達到。
使用上方的島嶼範例,您可以讓代理使用船而不是走過所有橋樑。
要使用此示例創建 PathfindingLink:
為了協助您更好地檢視和調試,切換在 路徑找鏈接 從 視覺化選項 widget 在右上角的 3D 視角。
在船上的座位上創建兩個 Attachments , 其中一個在船上的陸點附近。
在工作區中創建 PathfindingLink 對象,並且分別為起始和終止附件設定 附件0 和 附件1 屬性。
為其 Class.PathfindingLink.Label|Label 屬性命名有意義的名稱,例如 Label。這個名稱在路徑找隻機器中作為旗幟使用,當代理到達起始鏈接點時會啟動自訂動作。
包含 Costs 桌子內的表,其中包含一個 CreatePath() 鑰匙和一個自訂鑰匙,與 Water 屬性名稱相匹配。為自訂鑰匙設定更低值。
本地指令碼 - 角色路徑找求local PathfindingService = game:GetService("PathfindingService")local Players = game:GetService("Players")local RunService = game:GetService("RunService")local path = PathfindingService:CreatePath({Costs = {Water = 20,UseBoat = 1}})當 Class.PathfindingLink.Label|Label 發生時,添加自訂檢查對 Class.Humanoid:MoveTo() 修改器名稱,並且執行不同的操作,比如 Class.Humanoid:MoveTo() ,將代理從船上移動到目的地島,並且在目的地島上返回代理的路線。 Errors: Error: Class.Humanoid:
本地指令碼 - 角色路徑找求local PathfindingService = game:GetService("PathfindingService")local Players = game:GetService("Players")local RunService = game:GetService("RunService")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-- 如果「UseBoat」標誌,請使用船隻;否則移動到下一個「UseBoat」標誌if waypoints[nextWaypointIndex].Label == "UseBoat" thenuseBoat()elsehumanoid:MoveTo(waypoints[nextWaypointIndex].Position)endelsereachedConnection:Disconnect()blockedConnection:Disconnect()endend)end-- 最初移動到第二個 Waypoint (第一個 Waypoint 是路徑開啟動)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 空間。隨著他們探索 3D 空間,新的空間流量將從他們的裝置傳輸到其中一些基本參數,以及一些基本參數的基礎子集可能會從他們的裝置中流出。
考慮使用 PathfindingService 在啟用遊戲直播的體驗中的最佳練習:
流媒體可以以一個角色沿著它移動的方式來阻擋或解鎖指定的路徑。例如,當一個角色跑過森林時,樹可能會在某個地方前方串在路上,並且阻擋道路。為了使路徑與流媒體無縫地運行,它們強烈建議您使用 處理阻擋道路 技術,並在必要時重新計算
在路徑找求中使用已存在的對象的坐標來計算 距離 ,例如將路徑目的地設為存在的 寶箱 模型在世界上的位置。此方
為了解決此問題,請考慮將目的地設置在 BasePart 內的持續模型內。持續模型會在玩家加入後很快載入,並且永遠不會流出,因此客戶端腳本可以連接到 Class.Workspace.PersistentLoaded|PersistentLoaded 事件,並且在事件發生後安全地檢索模型。