字元路徑找求

*此內容是使用 AI(Beta 測試版)翻譯,可能含有錯誤。若要以英文檢視此頁面,請按一下這裡

路徑搜尋 是一個移動角色沿理想路徑到達目的地,避開障礙和 (可選) 危險材料或定義區域。

導航視覺化

要協助確定路徑找路和調試,Studio 可以渲染一個導航網格和 修改器 標籤。要啟用它們,請從 3D 視角上方右邊的 視窗選項 按鈕上的 導航網格 和 2>修改器2> 標籤切換。

A close up view of the 3D viewport with the Visualization Options button indicated in the upper-right corner.

啟用 導航網格 時,彩色區域會顯示角色可能走路或游泳的地方,而非彩色區域則會被鎖定。小箭頭指示角色將試著跳躍或游泳的地方,而不是顏色區域。當創建路徑時, AgentCanJump 會自動設置為 true ,假設您將 1>

Navigation mesh showing in Studio

啟用 路徑找尋模組 時,文字標籤會指示使用 路徑找尋模組 時所考慮的材料和區域。

Navigation labels showing on navigation mesh

已知的限制

路徑導航功能有特定限制,以確保有效的處理和最佳性履約。

垂直放置限制

路徑找到計算只考慮特定垂直邊界內的零件:

  • 低限制 — 底部 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決定是否允許在路徑導航中跳躍。booleantrue
AgentCanClimb決定是否允許在路徑找到期間 TrussPartsbooleanfalse
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 在路徑創建時設定 AgentCanClimbtrue 當路徑創建時,如果沒有什��

Path going up a climbable TrussPart ladder
本地指令碼 - 桁架攀爬路徑

local PathfindingService = game:GetService("PathfindingService")
local path = PathfindingService:CreatePath({
AgentCanClimb = true,
Costs = {
Climb = 2 -- 攀爬路的費用;預設為 1
}
})

沿路徑移動

此部分使用以下路徑查找指令碼為玩家的角色。要在閱讀時測試:

  1. 將代碼複製到 LocalScript 內的 StarterCharacterScripts 內。
  2. 編輯線 11 至 Vector3 玩家角色可以到達的目的地。
  3. 繼續前進以了解路徑計算和角色移動。
本地指令碼 - 角色路徑找求

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 start/end marked on series of islands and bridges

獲取方位點

一旦 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
Waypoints indicated across computed path
指定路徑的 Waypoints

道路移動

每個方位點包含一個 位置 ( 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() 返回最短路線,它與開始點和目的地之間的路線,除了跳過之外,這看起來不自然。在某些情況下, 路線通過水而不是通過附近的橋樑來避免跳躍。

Two paths indicated with the shorter path not necessarily more logical

為了進一步優化路徑搜尋,您可以實現 路徑搜尋模組 來計算更聰明的路徑在各種材料區域和1>障礙1>。

設定材料成本

使用 TerrainBasePart 材料時,您可以包含一個 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 對象到零件來達到此目標。

  1. 在危險區域周圍建立一個 Anchored 零件,並將其 CanCollide 屬性設置為 關閉。

    Anchored part defining a region to apply a pathfinding modifier to
  2. PathfindingModifier 實例插入零件,找到其 Label 屬性,並且指定一個有意義的名稱,例如 危險區

    PathfindingModifier instance with Label property set to DangerZone
  3. 包含 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
    }
    })

忽略障礙

在某些情況下,通過路徑找到通過路徑找到通過路徑不存在的障礙物。這允許您計算通過特定物理方塊的路徑,而不是計算失敗。

  1. 在對象周圍創建一個 Anchored 零件,並將其 CanCollide 屬性設置為 關閉

    Anchored part defining a region to apply a pathfinding modifier to
  2. PathfindingModifier 實例插入零件並啟用其 PassThrough 屬性。

    PathfindingModifier instance with PassThrough property enabled

    現在,當路徑從殭屍 NPC 至玩家角色時,路徑會從門延伸到外面,並且您可以提示殭屍穿過它。即使殭屍無法打開門,它也會反應像是 "聽"到門後的角色。

    Zombie NPC path passing through the previously blocking door

路徑查找連結

有時候需要找到一個通過空間無法正常穿越的路徑,例如穿過峭壁,並執行自訂行動來達到下一個方向點。這可以通過 PathfindingLink 物件來達到。

使用上方的島嶼範例,您可以讓代理使用船而不是走過所有橋樑。

PathfindingLink showing how an agent can use a boat instead of walking across all of the bridges

要使用此示例創建 PathfindingLink

  1. 為了協助您更好地檢視和調試,切換在 路徑找鏈接視覺化選項 widget 在右上角的 3D 視角。

  2. 在船上的座位上創建兩個 Attachments , 其中一個在船上的陸點附近。

    Attachments created for pathfinding link's start and end
  3. 在工作區中創建 PathfindingLink 對象,並且分別為起始和終止附件設定 附件0 和 附件1 屬性。

    Attachment0/Attachment1 properties of a PathfindingLink PathfindingLink visualized in the 3D world
  4. 為其 Class.PathfindingLink.Label|Label 屬性命名有意義的名稱,例如 Label。這個名稱在路徑找隻機器中作為旗幟使用,當代理到達起始鏈接點時會啟動自訂動作。

    Label property specified for PathfindingLink
  5. 包含 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
    }
    })
  6. 當 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.LocalPlayer
    local character = player.Character
    local humanoid = character:WaitForChild("Humanoid")
    local TEST_DESTINATION = Vector3.new(228.9, 17.8, 292.5)
    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
    -- 如果「UseBoat」標誌,請使用船隻;否則移動到下一個「UseBoat」標誌
    if waypoints[nextWaypointIndex].Label == "UseBoat" then
    useBoat()
    else
    humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
    end
    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
    function useBoat()
    local boat = workspace.BoatModel
    humanoid.Seated:Connect(function()
    -- 如果代理人坐下,開始船隻移動
    if humanoid.Sit then
    task.wait(1)
    boat.CylindricalConstraint.Velocity = 5
    end
    -- 與島嶼相關的限制位置偵測
    local boatPositionConnection
    boatPositionConnection = RunService.PostSimulation:Connect(function()
    -- 停止船隻,當島嶼靠近
    if boat.CylindricalConstraint.CurrentPosition >= 94 then
    boatPositionConnection:Disconnect()
    boat.CylindricalConstraint.Velocity = 0
    task.wait(1)
    -- 取下代理並繼續目的地
    humanoid.Sit = false
    humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
    end
    end)
    end)
    end
    followPath(TEST_DESTINATION)

流媒體兼容性

在體驗中 場景串流 是一種強大的功能,可以動態載入和卸載 3D 內容,讓玩家的角色在世界上探索 3D 空間。隨著他們探索 3D 空間,新的空間流量將從他們的裝置傳輸到其中一些基本參數,以及一些基本參數的基礎子集可能會從他們的裝置中流出。

考慮使用 PathfindingService 在啟用遊戲直播的體驗中的最佳練習:

  • 流媒體可以以一個角色沿著它移動的方式來阻擋或解鎖指定的路徑。例如,當一個角色跑過森林時,樹可能會在某個地方前方串在路上,並且阻擋道路。為了使路徑與流媒體無縫地運行,它們強烈建議您使用 處理阻擋道路 技術,並在必要時重新計算

  • 在路徑找求中使用已存在的對象的坐標來計算 距離 ,例如將路徑目的地設為存在的 寶箱 模型在世界上的位置。此方

    為了解決此問題,請考慮將目的地設置在 BasePart 內的持續模型內。持續模型會在玩家加入後很快載入,並且永遠不會流出,因此客戶端腳本可以連接到 Class.Workspace.PersistentLoaded|PersistentLoaded 事件,並且在事件發生後安全地檢索模型。