Trovare il percorso è il processo di spostare un personaggio lungo un percorso logico per raggiungere una destinazione, evitando ostacoli e (opzionalmente) materiali pericolosi o regioni definite.
Visualizzazione della navigazione
Per aiutare con la ricerca del percorso e il debugging, Studio può rendere una griglia di navigazione e modificatori etichette.Per abilitarli, attiva mesh di navigazione e modificatori di percorso dalla finestra Opzioni di visualizzazione nell'angolo in alto a destra della vista 3D.

Con mesh di navigazione abilitata, le aree colorate mostrano dove un personaggio potrebbe camminare o nuotare, mentre le aree non colorate sono bloccate.Le piccole frecce indicano le aree che un personaggio cercherà di raggiungere saltando, supponendo che tu abbia impostato AgentCanJump su true quando crei il percorso .

Con modificatori di ricerca di percorso abilitati, le etichette di testo indicano materiali e regioni specifici che vengono presi in considerazione quando si utilizzano modificatori di ricerca di percorso.

Limiti noti
Le funzionalità di trova percorso hanno limitazioni specifiche per garantire un'efficace elaborazione e Prestazioneottimali.
Limite di posizionamento verticale
I calcoli di ricerca del percorso considerano solo le parti all'interno di determinati confini verticali:
- Sottolimitazione — Le parti con una coordinata inferiore Y a meno di -65,536 stud sono ignorate.
- Limite superiore — Le parti con una coordinata superiore Y che supera 65,536 studs vengono ignorate.
- Intervallo verticale — La distanza verticale dal fondo della parte più bassa Y alla coordinata della parte più alta Y non deve superare 65,536 borchie; altrimenti, il sistema di ricerca del percorso ignorerà quelle parti durante il calcolo della ricerca del percorso.
Limite di distanza di ricerca
La distanza lineare diretta per la ricerca del percorso dall'inizio al punto di arrivo non deve superare 3.000 studs.Superare questa distanza comporterà uno StatoNoPath di >.
Crea sentieri
La ricerca del percorso viene inizializzata attraverso PathfindingService e la sua funzione CreatePath().
Script locale
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath()
CreatePath() accetta una tabella opzionale di parametri che ottimizza il modo in cui il personaggio (agente) si muove lungo il percorso.
Chiave | Descrizione | Tipo | Basilare |
---|---|---|---|
AgentRadius | Raggio dell'agente, in studs. Utile per determinare la separazione minima dagli ostacoli. | integro | 2 |
AgentHeight | Altezza dell'agente, in studs. Lo spazio vuoto più piccolo di questo valore, come lo spazio sotto le scale, sarà contrassegnato come non percorribile. | integro | 5 |
AgentCanJump | Determina se è consentito saltare durante la ricerca del percorso. | booleano | true |
AgentCanClimb | Determina se è consentito salire TrussParts durante la ricerca del percorso. | booleano | false |
WaypointSpacing | Spaziatura tra i punti di percorso intermedi nel percorso. Se impostato su math.huge, non ci saranno punti di percorso intermedi. | numbero | 4 |
Costs | Tabella dei materiali o definita PathfindingModifiers e il loro costo per la traversal.Utile per far preferire all'agente determinati materiali/regioni rispetto ad altri.Vedi modificatori per i dettagli. | tavola | nil |
Script locale
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath({AgentRadius = 3,AgentHeight = 6,AgentCanJump = false,Costs = {Water = 20}})
Nota che l'agente può salire TrussParts durante la ricerca del percorso supponendo che tu imposti AgentCanClimb a true quando crei il percorso e nulla blocca l'agente dal percorso di salita della truss.Un percorso salibile ha il Etichetta di salita e il costo per un percorso salibile è 1 per impostazione predefinita.

Script locale - Pathdi arrampicata sul truss
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath({AgentCanClimb = true,Costs = {Climb = 2 -- Costi del percorso di arrampicata; il valore predefinito è 1}})
Muoviti lungo i percorsi
Questa sezione utilizza lo script di ricerca del percorso seguente per il personaggio del Giocatore. Per testare mentre si legge:
- Copia il codice in un LocalScript entro StarterCharacterScripts .
- Imposta la variabile TEST_DESTINATION a una destinazione Vector3 nel tuo mondo 3D a cui il personaggio del giocatore può raggiungere.
- Procedi attraverso le seguenti sezioni per imparare a conoscere la calcolata del percorso e il movimento dei personaggi.
Script locale - Trova il percorso dei personaggi
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)
-- Calcola il percorso
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Ottieni i punti di percorso
waypoints = path:GetWaypoints()
-- Rileva se il percorso diventa bloccato
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Verifica se l'ostacolo è più in basso sul percorso
if blockedWaypointIndex >= nextWaypointIndex then
-- Interrompi il rilevamento del blocco del percorso fino a quando il percorso non viene ricomputato
blockedConnection:Disconnect()
-- Chiama la funzione per ricomputare il nuovo percorso
followPath(destination)
end
end)
-- Rileva quando il movimento al punto di destinazione successivo è completo
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- Aumenta l'indice dei punti di percorso e muoviti al prossimo punto di percorso
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- Inizialmente spostati al secondo punto di passaggio (il primo punto di passaggio è l'Iniziare, cominciaredel percorso; saltalo)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
followPath(TEST_DESTINATION)
Calcola il percorso
Dopo aver creato un percorso valido con CreatePath() , deve essere calcolato chiamando Path:ComputeAsync() con un Vector3 per entrambi il punto di partenza e la destinazione.
Script locale - Trova il percorso dei personaggi
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)
-- Calcola il percorso
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
end

Ottieni waypoint
Una volta calcolato il Path, conterrà una serie di punti di percorso che tracciano il percorso dall'inizio alla Terminare.Questi punti possono essere raccolti con la funzione Path:GetWaypoints() .
Script locale - Trova il percorso dei personaggi
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)
-- Calcola il percorso
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Ottieni i punti di percorso
waypoints = path:GetWaypoints()
end
end

Movimento del percorso
Ogni punto di riferimento consiste in entrambi una posizione ( ) e un'azione ( ) .Per spostare un personaggio che contiene un Humanoid , come un tipico personaggio Roblox, il modo più semplice è chiamare Humanoid:MoveTo() da punto di percorso a punto di percorso, utilizzando l'evento MoveToFinished per rilevare quando il personaggio raggiunge ogni punto di percorso.
Script locale - Trova il percorso dei personaggi
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)
-- Calcola il percorso
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Ottieni i punti di percorso
waypoints = path:GetWaypoints()
-- Rileva se il percorso diventa bloccato
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Verifica se l'ostacolo è più in basso sul percorso
if blockedWaypointIndex >= nextWaypointIndex then
-- Interrompi il rilevamento del blocco del percorso fino a quando il percorso non viene ricomputato
blockedConnection:Disconnect()
-- Chiama la funzione per ricomputare il nuovo percorso
followPath(destination)
end
end)
-- Rileva quando il movimento al punto di destinazione successivo è completo
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- Aumenta l'indice dei punti di percorso e muoviti al prossimo punto di percorso
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- Inizialmente spostati al secondo punto di passaggio (il primo punto di passaggio è l'Iniziare, cominciaredel percorso; saltalo)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
Maneggiare percorsi bloccati
Molti mondi di Roblox sono dinamici; le parti possono muoversi o cadere e i pavimenti possono crollare.Questo può bloccare un percorso calcolato e impedire al personaggio di raggiungere la destinazione.Per gestire questo, puoi connettere l'evento Path.Blocked e ricomputare il percorso intorno a ciò che lo ha bloccato.
Script locale - Trova il percorso dei personaggi
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)
-- Calcola il percorso
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Ottieni i punti di percorso
waypoints = path:GetWaypoints()
-- Rileva se il percorso diventa bloccato
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Verifica se l'ostacolo è più in basso sul percorso
if blockedWaypointIndex >= nextWaypointIndex then
-- Interrompi il rilevamento del blocco del percorso fino a quando il percorso non viene ricomputato
blockedConnection:Disconnect()
-- Chiama la funzione per ricomputare il nuovo percorso
followPath(destination)
end
end)
end
end
Modificatori di pathfinding
Per impostazione predefinita, restituisce il percorso più breve tra il punto di partenza e la destinazione, con l'eccezione che tenta di evitare i salti.Questo sembra innaturale in alcune situazioni - per esempio, un percorso può passare attraverso l'acqua piuttosto che su un ponte vicino semplicemente perché il percorso attraverso l'acqua è geometricamente più breve.

Per ottimizzare ulteriormente la ricerca del percorso, puoi implementare modificatori di ricerca del percorso per calcolare percorsi più intelligenti attraverso vari materiali, intorno a regioni definite, o attraverso ostacles.
Imposta i costi del materiale
Lavorando con Terrain e BasePart materiali, puoi includere una tabella Costs all'interno di CreatePath() per rendere alcuni materiali più trasponibili di altri.Tutti i materiali hanno un costo predefinito di 1 e qualsiasi materiale può essere definito non attraversabile impostando il suo valore a math.huge .
Le chiavi nella tabella Costs dovrebbero essere nomi di stringa che rappresentano Enum.Material nomi, ad esempio Water per Enum.Material.Water .
Script locale - Trova il percorso dei personaggi
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}})
Lavora con le regioni
In alcuni casi, preferenza del materiale non è sufficiente.Ad esempio, potresti volere che i personaggi evitino una regione definita , indipendentemente dai materiali sottostanti.Questo può essere ottenuto aggiungendo un oggetto PathfindingModifier a una parte.
Crea una parte Anchored attorno alla regione pericolosa e imposta la sua proprietà CanCollide a falso .
Inserisci un'istanza PathfindingModifier su parte, individua la sua ProprietàLabel e assegna un nome significativo come DangerZone .
Includi una tabella Costs all'interno di CreatePath() contenente una chiave corrispondente e un valore numerico associato.Un modificatore può essere definito non attraversabile impostando il suo valore a math.huge .
Script locale - Trova il percorso dei personaggilocal 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}})
Ignora gli ostacoli
In alcuni casi, è utile trovare il percorso attraverso ostacoli solidi come se non esistessero.Questo ti consente di calcolare un percorso attraverso blocchi fisici specifici, rispetto alla mancata esecuzione della computazione.
Crea una parte Anchored attorno all'oggetto e imposta la sua proprietà CanCollide a falso .
Inserisci un'istanza PathfindingModifier su parte e abilita la sua ProprietàPassThrough.
Ora, quando un percorso viene calcolato dal NPC zombie al personaggio del giocatore, il percorso si estende oltre la porta e puoi richiedere allo zombie di attraversarlo.Anche se lo zombie non è in grado di aprire la porta, reagisce come se "sentisse" il personaggio dietro la porta.
Link di ricerca del percorso
A volte è necessario trovare un percorso attraverso uno spazio che non può essere normalmente attraversato, come attraverso un abisso, e eseguire un'azione personalizzata per raggiungere il prossimo punto d'interesse.Questo può essere ottenuto attraverso l'oggetto PathfindingLink.
Usando l'esempio dell'isola dall'alto, puoi far usare all'agente una barca invece di camminare su tutti i ponti.

Per creare un PathfindingLink utilizzando questo esempio:
Per assistere con la visualizzazione e il debug, attiva collegamenti di ricerca del percorso dal widget Opzioni di visualizzazione nell'angolo in alto a destra della finestra3D.
Crea due Attachments , uno sul sedile della barca e uno vicino al punto di atterraggio della barca.
Crea un oggetto PathfindingLink nell'area di lavoro, quindi assegna le sue proprietà Attachment0 e Attachment1 alle rispettive allegature iniziali e finali.
Assegna un nome significativo come UseBoat alla sua ProprietàLabel.Questo nome viene utilizzato come bandiera nello script di ricerca del percorso per attivare un'azione personalizzata quando l'agente raggiunge il punto di collegamento iniziale.
Includi una tabella contenente sia una chiave e una chiave personalizzata corrispondente al nome della proprietà .Assegna alla chiave personalizzata un valore più basso di Water .
Script locale - Trova il percorso dei personaggilocal 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}})Nell'evento che si attiva quando un punto di passaggio viene raggiunto, aggiungi un controllo personalizzato per il nome del modificatore Label e intraprendi un'azione diversa da quella di Humanoid:MoveTo() — in questo caso, chiama una funzione per sedere l'agente nella barca, muoverla attraverso l'acqua e continuare il percorso dell'agente all'arrivo sull'isola di destinazione.
Script locale - Trova il percorso dei personaggilocal 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)-- Calcola il percorsolocal success, errorMessage = pcall(function()path:ComputeAsync(character.PrimaryPart.Position, destination)end)if success and path.Status == Enum.PathStatus.Success then-- Ottieni i punti di percorsowaypoints = path:GetWaypoints()-- Rileva se il percorso diventa bloccatoblockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)-- Verifica se l'ostacolo è più in basso sul percorsoif blockedWaypointIndex >= nextWaypointIndex then-- Interrompi il rilevamento del blocco del percorso fino a quando il percorso non viene ricomputatoblockedConnection:Disconnect()-- Chiama la funzione per ricomputare il nuovo percorsofollowPath(destination)endend)-- Rileva quando il movimento al punto di destinazione successivo è completoif not reachedConnection thenreachedConnection = humanoid.MoveToFinished:Connect(function(reached)if reached and nextWaypointIndex < #waypoints then-- Aumenta l'indice dei punti di percorso e muoviti al prossimo punto di percorsonextWaypointIndex += 1-- Usa la barca se l'etichetta waypoint è "UseBoat"; altrimenti spostati al prossimo waypointif waypoints[nextWaypointIndex].Label == "UseBoat" thenuseBoat()elsehumanoid:MoveTo(waypoints[nextWaypointIndex].Position)endelsereachedConnection:Disconnect()blockedConnection:Disconnect()endend)end-- Inizialmente spostati al secondo punto di passaggio (il primo punto di passaggio è l'Iniziare, cominciaredel percorso; saltalo)nextWaypointIndex = 2humanoid:MoveTo(waypoints[nextWaypointIndex].Position)elsewarn("Path not computed!", errorMessage)endendfunction useBoat()local boat = Workspace.BoatModelhumanoid.Seated:Connect(function()-- Avvia la barca in movimento se l'agente è sedutoif humanoid.Sit thentask.wait(1)boat.CylindricalConstraint.Velocity = 5end-- Rileva la posizione della restrizione in relazione all'isolalocal boatPositionConnectionboatPositionConnection = RunService.PostSimulation:Connect(function()-- Fermare la barca quando accanto all'isolaif boat.CylindricalConstraint.CurrentPosition >= 94 thenboatPositionConnection:Disconnect()boat.CylindricalConstraint.Velocity = 0task.wait(1)-- Siediti l'agente e continua alla destinazionehumanoid.Sit = falsehumanoid:MoveTo(waypoints[nextWaypointIndex].Position)endend)end)endfollowPath(TEST_DESTINATION)
Compatibilità di streaming
Lo streaming dell'istanza in-experience in tempo reale è una potente funzione che carica e scarica dinamicamente il contenuto 3D mentre un personaggio del Giocatoresi muove in tutto il Mondo.Mentre esplorano lo Spazio3D, nuovi sottinsiemi dello stream spaziale vengono inviati al loro dispositivo e alcuni dei sottinsiemi esistenti potrebbero essere trasmessi.
Considera le seguenti migliori pratiche per l'utilizzo di PathfindingService in esperienze abilitate allo streaming:
Lo streaming può bloccare o sbloccare un percorso dato mentre un personaggio lo percorre.Ad esempio, mentre un personaggio attraversa una foresta, un albero potrebbe streamare in qualche posto prima di loro e ostacolare il percorso.Per rendere il lavoro di ricerca del percorso senza soluzione di continuità con lo streaming, è altamente raccomandato utilizzare la tecnica gestire i percorsi bloccati e ricomputare il percorso quando necessario.
Un approccio comune nel trovare il percorso è quello di utilizzare le coordinate di oggetti esistenti per calcolo, come impostare una destinazione di percorso alla posizione di un modello Cassetta del Tesoro esistente nel Mondo.Questo approccio è pienamente compatibile con il lato server Scripts poiché il server ha una visione completa del mondo in ogni momento, ma LocalScripts e ModuleScripts quelli che si eseguono sul client possono fallire se tentano di calcolare un percorso verso un oggetto che non viene trasmesso in.
Per risolvere questo problema, considera di impostare la destinazione alla posizione di un BasePart all'interno di un modello persistente persistente.I modelli persistenti si caricano poco dopo che il giocatore si unisce e non vengono mai trasmessi, quindi uno script lato client può connettersi all'evento PersistentLoaded e accedere in sicurezza al modello per creare punti di percorso dopo l'evento.