Znajdowanie ścieżki to proces przemieszczania postaci wzdłuż logicznej ścieżki, aby dotrzeć do celu, unikając przeszkód i (opcjonalnie) niebezpiecznych materiałów lub określonych regionów.
Wizualizacja nawigacji
Aby pomóc w wyszukiwaniu ścieżki i debugowaniu, Studio może wyrenderować siatkę nawigacyjną i etykiety modyfikatora.Aby je włączyć, przełącz sieć nawigacyjną i modyfikatory znajdowania ścieżki z menu Opcje wizualizacji w prawym górnym rogu widoku 3D.

Z włączoną siatką nawigacji , kolorowe obszary pokazują, gdzie może chodzić lub pływaniepostać, a niekolorowe są zablokowane.Małe strzałki wskazują obszary, do których postać będzie próbować dotrzeć, skacząc, zakładając, że ustawiłeś AgentCanJump na true, gdy tworzyłeś ścieżkę.

Z włączonymi modyfikatorami wyszukiwania ścieżki , etykiety tekstowe wskazują na konkretne materiały i regiony, które są brane pod uwagę przy użyciu modyfikatorów wyszukiwania ścieżki.

Znane ograniczenia
Funkcje wyszukiwania ścieżek mają określone ograniczenia, aby zapewnić wydajną obróbkę i optymalną wykonywanie.
Ograniczenie umieszczenia w pionie
Kalkulacje wyszukiwania ścieżek rozważają tylko części w ramach pewnych pionowych granic:
- Dolna granica — Części z dolną koordynatą Y mniejszą niż -65,536 szpilkami są ignorowane.
- Górna granica — Części z górną koordynatą Y , przekraczającą 65,536 śrub, są ignorowane.
- Przestrzeń pionowa — Przestrzeń pionowa od dołu Y koordynaty najniższej części do góry Y koordynaty najwyższej części nie może przekroczyć 65,536 ćwieków; w przeciwnym razie system wyszukiwania ścieżek zignoruje te części podczas obliczeń ścieżki.
Ograniczenie dystansu wyszukiwania
Bezpośrednia odległość widzenia dla odnajdywania ścieżki od początku do punktu końcowego nie może przekroczyć 3,000 szpilkami.Przekroczenie tej odległości spowoduje stan NoPath .
Twórz ścieżki
Wyszukiwanie ścieżki jest uruchamiane za pośrednictwem PathfindingService i jego funkcji CreatePath().
Lokalny skrypt
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath()
CreatePath() akceptuje opcjonalny stół parametrów, który dostosowuje sposób poruszania się postaci (agent) wzdłuż ścieżki.
Klucz | Opis | Typ | Domyślny |
---|---|---|---|
AgentRadius | Promień agenta, w szpilkach. Przydatny do określenia minimalnej odległości od przeszkód. | liczba całkowita | 2 |
AgentHeight | Wysokość agenta, w szpilkach. Pusta przestrzeń mniejsza niż ta wartość, tak jak przestrzeń pod schodami, zostanie oznaczona jako niedostępna. | liczba całkowita | 5 |
AgentCanJump | Określa, czy dozwolone jest skakanie podczas wyszukiwania ścieżki. | booleanowy | true |
AgentCanClimb | Określa, czy wspinanie się TrussParts podczas wyszukiwania ścieżki jest dozwolone. | booleanowy | false |
WaypointSpacing | Odległość między pośrednimi punktami trasy w ścieżce. Jeśli ustawisz ją na math.huge, nie będzie pośrednich punktów trasy. | number liczba | 4 |
Costs | Tabela materiałów lub zdefiniowane PathfindingModifiers i ich koszt za przebieg.Przydatne do tego, aby agent preferował pewne materiały/regiony nad innymi.Zobacz modyfikatory dla szczegółów. | stół | nil |
Lokalny skrypt
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath({AgentRadius = 3,AgentHeight = 6,AgentCanJump = false,Costs = {Water = 20}})
Zauważ, że agent może wspinać się TrussParts podczas wyszukiwania ścieżki, zakładając, że ustawiłeś AgentCanClimb na true, gdy tworzono ścieżkę i nic nie blokuje agenta z ścieżki wspinania się po trussie.Schodząca ścieżka ma etykietę Wejdź i koszt za schodzącą ścieżkę jest domyślnie 1 .

LocalScript - Ścieżka wspinania się na rusztach
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath({AgentCanClimb = true,Costs = {Climb = 2 -- Koszt ścieżki wspinaczkowej; domyślnie jest to 1}})
Poruszaj się po ścieżkach
Ta sekcja używa następującego skryptu wyszukiwania ścieżki dla postaci gracza. Aby przetestować podczas czytania:
- Kopiuj kod do LocalScript w ciągu StarterCharacterScripts .
- Ustaw zmienną TEST_DESTINATION na cel Vector3 w twoim świecie 3D, do którego może dotrzeć postać gracza.
- Przejdź przez następujące sekcje, aby dowiedzieć się o obliczaniu ścieżki i ruchu postaci.
LocalScript - Wyszukiwanie ścieżki postaci
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)
-- Oblicz ścieżkę
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Zdobądź punkty ścieżki
waypoints = path:GetWaypoints()
-- Wykryj, czy ścieżka zablokuje się
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Sprawdź, czy przeszkoda jest dalej w dół ścieżki
if blockedWaypointIndex >= nextWaypointIndex then
-- Zatrzymaj wykrywanie blokady ścieżki, dopóki ścieżka nie zostanie ponownie obliczona
blockedConnection:Disconnect()
-- Wezwij funkcję, aby ponownie obliczyć nową ścieżkę
followPath(destination)
end
end)
-- Wykryj, kiedy przemiana do następnego punktu docelowego jest zakończona
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- Zwiększ indeks punktów drogi i przejdź do następnego punktu drogi
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- Początkowo przejdź do drugiego punktu docelowego (pierwszy punkt docelowy to rozpoczynaćścieżki; pomiń go)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
followPath(TEST_DESTINATION)
Oblicz ścieżkę
Po utworzeniu ważnej ścieżki z CreatePath() musi być obliczona poprzez wezwanie Path:ComputeAsync() z Vector3 dla punktu startowego i docelowego.
LocalScript - Wyszukiwanie ścieżki postaci
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)
-- Oblicz ścieżkę
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
end

Zdobądź punkty drogi
Gdy Path zostanie obliczony, będzie zawierał szereg punktów drogi , które śledzą ścieżkę od początku do kończyć.Punkty te można zebrać za pomocą funkcji Path:GetWaypoints().
LocalScript - Wyszukiwanie ścieżki postaci
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)
-- Oblicz ścieżkę
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Zdobądź punkty ścieżki
waypoints = path:GetWaypoints()
end
end

Poruszanie ścieżki
Każdy punkt orientacyjny składa się zarówno z pozycji () oraz akcji ( ).Aby przenieść postać zawierającą Humanoid , tak jak typowy postać Roblox, najłatwiejszym sposobem jest wezwanie Humanoid:MoveTo() z punktu do punktu, używając wydarzenia MoveToFinished , aby wykryć, kiedy postać dotrze do każdego punktu.
LocalScript - Wyszukiwanie ścieżki postaci
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)
-- Oblicz ścieżkę
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Zdobądź punkty ścieżki
waypoints = path:GetWaypoints()
-- Wykryj, czy ścieżka zablokuje się
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Sprawdź, czy przeszkoda jest dalej w dół ścieżki
if blockedWaypointIndex >= nextWaypointIndex then
-- Zatrzymaj wykrywanie blokady ścieżki, dopóki ścieżka nie zostanie ponownie obliczona
blockedConnection:Disconnect()
-- Wezwij funkcję, aby ponownie obliczyć nową ścieżkę
followPath(destination)
end
end)
-- Wykryj, kiedy przemiana do następnego punktu docelowego jest zakończona
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- Zwiększ indeks punktów drogi i przejdź do następnego punktu drogi
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- Początkowo przejdź do drugiego punktu docelowego (pierwszy punkt docelowy to rozpoczynaćścieżki; pomiń go)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
Ręczne blokowanie ścieżek
Wiele światów Roblox jest dynamicznych; części mogą się poruszać lub upadać, a podłogi mogą się zawalić.Może to zablokować wyliczany ścieżek i uniemożliwić osiągnięcie celu przez postać.Aby sobie z tym poradzić, możesz połączyć wydarzenie Path.Blocked i ponownie obliczyć ścieżkę wokół czegoś, co go zablokowało.
LocalScript - Wyszukiwanie ścieżki postaci
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)
-- Oblicz ścieżkę
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Zdobądź punkty ścieżki
waypoints = path:GetWaypoints()
-- Wykryj, czy ścieżka zablokuje się
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Sprawdź, czy przeszkoda jest dalej w dół ścieżki
if blockedWaypointIndex >= nextWaypointIndex then
-- Zatrzymaj wykrywanie blokady ścieżki, dopóki ścieżka nie zostanie ponownie obliczona
blockedConnection:Disconnect()
-- Wezwij funkcję, aby ponownie obliczyć nową ścieżkę
followPath(destination)
end
end)
end
end
Modyfikatory znajdowania ścieżki
Domyślnie, zwraca najkrótszą ścieżkę pomiędzy punktem startowym a docelowym, z wyjątkiem, że próbuje unikać skoków.W niektórych sytuacjach wygląda to nienaturalnie - na instancjaścieżka może przejść przez wodę, a nie nad pobliską bramą, ponieważ ścieżka przez wodę jest geometrycznie krótsza.

Aby jeszcze bardziej zoptymalizować wyszukiwanie ścieżki, możesz wdrożyć modyfikatory wyszukiwania ścieżki , aby obliczyć bardziej inteligentne ścieżki na różnych materiałach, wokół zdefiniowanych regionów lub poprzez przeszkody.
Ustaw koszty materiałów
Pracując z materiałami Terrain i BasePart, możesz dodać tabelę Costs w ramach CreatePath(), aby niektóre materiały były bardziej przemijalne niż inne.Wszystkie materiały mają domyślną cenę 1 i każdy materiał może zostać zdefiniowany jako niedostępny, ustawiając jego wartość na math.huge .
Klucze w tabeli Costs powinny być nazwami strun reprezentującymi nazwy Enum.Material na przykład Water dla Enum.Material.Water.
LocalScript - Wyszukiwanie ścieżki postaci
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}})
Pracuj z regionami
W niektórych przypadkach preferencja materiału nie wystarcza.Na przykład możesz chcieć, aby postacie unikały obszaru zdefiniowanego regionu , niezależnie od materiałów pod stopami.Można to osiągnąć, dodając obiekt PathfindingModifier do części.
Stwórz część Anchored wokół niebezpiecznego regionu i ustaw jego właściwość CanCollide na fałsz .
Wstaw instancję PathfindingModifier na część, znajdź jej właściwość Label i przypisz znaczącą nazwę, taką jak DangerZone .
Umieść w tabeli Costs zawierającą pasujący klucz i powiązaną wartość liczbową znacznik CreatePath().Modyfikator może zostać zdefiniowany jako niedostępny poprzez ustawienie jego wartości na math.huge .
LocalScript - Wyszukiwanie ścieżki postacilocal 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}})
Ignoruj przeszkody
W niektórych przypadkach przydatne jest znalezienie ścieżki przez solidne przeszkody, tak jakby nie istniały.Umożliwia to obliczenie ścieżki poprzez określone blokery fizyczne w porównaniu z porażką obliczeń.
Stwórz część Anchored wokół obiektu i ustaw jego właściwość CanCollide na fałsz .
Wstaw instancję PathfindingModifier na część i włącz jej właściwość PassThrough.
Teraz, gdy ścieżka jest obliczana z zombie NPC do postaci gracza, ścieżka rozciąga się poza drzwi i możesz poprosić zombie o przemknięcie jej.Nawet jeśli zombie nie jest w stanie otworzyć drzwi, reaguje tak, jakby "słyszało" postać za drzwiami.
Linki do znajdowania ścieżki
Czasami konieczne jest znalezienie ścieżki przez przestrzeń, której nie można normalnie przemierzać, na przykład przez wąwóz, i wykonanie niestandardowej akcji, aby dotrzeć do następnego punktu docelowego.Można to osiągnąć za pomocą obiektu PathfindingLink.
Używając przykładu wyspy z powyższego, możesz sprawić, że agent używa łodzi zamiast chodzić po wszystkich mostach.

Aby utworzyć PathfindingLink używając tego przykładu:
Aby pomóc w wizualizacji i debugowaniu, przełącz łącza znajdowania ścieżki z menu Opcje wizualizacji w prawym górnym rogu widoku 3D.
Stwórz dwa Attachments , jedno na siedzeniu łodzi i jedno w pobliżu punktu lądowania łodzi.
Utwórz obiekt PathfindingLink w przestrzeni roboczej, a następnie przypisz jego właściwości Attachment0 i Attachment1 do początkowych i końcowych załączników odpowiednio.
Nadaj znaczącą nazwę, taką jak UseBoat do jego właściwości Label.Nazwa ta jest używana jako flaga w skrypcie wyszukiwania ścieżki, aby uruchomić niestandardową akcję, gdy agent dotrze do punktu początkowego linku.
Umieść w tabeli zawierającą zarówno klucz jak i niestandardowy klucz pasujący do nazwy właściwości .Nadaj niższą wartość klucza niż Water .
LocalScript - Wyszukiwanie ścieżki postacilocal 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}})W wydarzeniu, które uruchamia się, gdy osiągnięto punkt docelowy, dodaj niestandardowe sprawdzenie dla nazwy modyfikatora Label i podjęj inną akcję niż Humanoid:MoveTo() - w tym przypadku wezwij funkcję, aby umieścić agenta w łodzi, przepłynąć po wodzie i kontynuować ścieżkę agenta po przybyciu na docelową wyspę.
LocalScript - Wyszukiwanie ścieżki postacilocal 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)-- Oblicz ścieżkęlocal success, errorMessage = pcall(function()path:ComputeAsync(character.PrimaryPart.Position, destination)end)if success and path.Status == Enum.PathStatus.Success then-- Zdobądź punkty ścieżkiwaypoints = path:GetWaypoints()-- Wykryj, czy ścieżka zablokuje sięblockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)-- Sprawdź, czy przeszkoda jest dalej w dół ścieżkiif blockedWaypointIndex >= nextWaypointIndex then-- Zatrzymaj wykrywanie blokady ścieżki, dopóki ścieżka nie zostanie ponownie obliczonablockedConnection:Disconnect()-- Wezwij funkcję, aby ponownie obliczyć nową ścieżkęfollowPath(destination)endend)-- Wykryj, kiedy przemiana do następnego punktu docelowego jest zakończonaif not reachedConnection thenreachedConnection = humanoid.MoveToFinished:Connect(function(reached)if reached and nextWaypointIndex < #waypoints then-- Zwiększ indeks punktów drogi i przejdź do następnego punktu droginextWaypointIndex += 1-- Użyj łodzi, jeśli etykieta punktu docelowego jest "UseBoat"; w przeciwnym razie przejdź do następnego punktu docelowegoif waypoints[nextWaypointIndex].Label == "UseBoat" thenuseBoat()elsehumanoid:MoveTo(waypoints[nextWaypointIndex].Position)endelsereachedConnection:Disconnect()blockedConnection:Disconnect()endend)end-- Początkowo przejdź do drugiego punktu docelowego (pierwszy punkt docelowy to rozpoczynaćścieżki; pomiń go)nextWaypointIndex = 2humanoid:MoveTo(waypoints[nextWaypointIndex].Position)elsewarn("Path not computed!", errorMessage)endendfunction useBoat()local boat = Workspace.BoatModelhumanoid.Seated:Connect(function()-- Rozpocznij ruch statku, jeśli agent jest siedzonyif humanoid.Sit thentask.wait(1)boat.CylindricalConstraint.Velocity = 5end-- Wykryj pozycję ograniczenia w odniesieniu do wyspylocal boatPositionConnectionboatPositionConnection = RunService.PostSimulation:Connect(function()-- Zatrzymaj łódź, gdy obok wyspyif boat.CylindricalConstraint.CurrentPosition >= 94 thenboatPositionConnection:Disconnect()boat.CylindricalConstraint.Velocity = 0task.wait(1)-- Odłóż agenta i kontynuuj podróż do celuhumanoid.Sit = falsehumanoid:MoveTo(waypoints[nextWaypointIndex].Position)endend)end)endfollowPath(TEST_DESTINATION)
Kompatybilność z transmisją
In-experience przepływ instancji to potężna funkcja, która dynamicznie ładowuje i rozładowuje treści 3D, gdy postać gracza porusza się po świecie.W miarę eksplorowania przestrzeni 3D nowe podzespoły przepływu przestrzeni trafiają do ich urządzenia, a niektóre z istniejących podzespołów mogą wyciekać.
Rozważ następujące najlepsze praktyki dotyczące używania PathfindingService w doświadczeniach umożliwiających strumieniowanie:
Streamowanie może blokować lub odblokowywać dany ścieżek, gdy postać porusza się po nim.Na przykład, podczas gdy postać przemierza las, drzewo może przepływać gdzieś przed nią i blokować ścieżkę.Aby wyszukiwanie ścieżki płynnie współpracowało z przesyłaniem, zdecydowanie zaleca się użycie techniki przetwarzania zablokowanych ścieżek i ponowne obliczanie ścieżki w razie potrzeby.
Powszechnym podejściem w odnajdywaniu ścieżki jest użycie koordynatów istniejących obiektów do obliczeń, takich jak ustawienie celu ścieżki na pozycję modelu Skrzyni Skarbów istniejącego w świecie.Ta metoda jest w pełni kompatybilna z stroną serwera Scripts, ponieważ serwer ma pełny widok świata przez cały czas, ale LocalScripts i ModuleScripts, które uruchamiają się na klientzie, mogą zawieść, jeśli próbują obliczyć ścieżkę do obiektu, który nie jest przesyłany.
Aby rozwiązać ten problem, rozważ ustawienie celu na pozycję BasePart w ramach modelu trwałego.Modelami trwałymi ładowane są wkrótce po dołączeniu gracza i nigdy nie są transmitowane, więc skrypt stronny może połączyć się z wydarzeniem PersistentLoaded i bezpiecznie uzyskać dostęp do modelu do tworzenia punktów ścieżki po wystrzeleniu wydarzenia.