Wegfindung ist der Prozess, einen Charakter entlang eines logischen Wegs zu bewegen, um einen Zielort zu erreichen, ohne Hindernisse und (optional) gefahrgut oder definierte Regionen zu vermeiden.
Navigationsvisualisierung
Um bei der Navigations路径-Entdeckung und -Debugging-Hilfe zu geben, kann Studio eine Navigationsmeshes und Modifier- Labels rendern. Um sie zu aktivieren, schalten Sie Navigationsmeshes und Modifier- Labels von der 2> Visualisierung-Optionen2>-Werte in der oberen rechten Ecke des 3D-Ansichtsfensters um.
Mit Navigationsnetzwerk aktiviert, zeigen farbige Bereiche an, wo ein Charakter gehen oder schwimmen kann, während nicht farbige Bereiche blockiert sind. Die kleinen Pfeile zeigen Bereiche an, die ein Charakter versuchen wird, durch Springen zu erreichen, wenn Sie AgentCanJump auf true setzen, wenn Sie den Pfad erstellen.
Mit Wegfindungs-Modifikatoren aktiviert, zeigen Text-Etiketten spezifische Materialien und Regionen an, die beim Gebrauch von Wegfindungs-Modifikatoren berücksichtigt werden.
Bekannte Einschränkungen
Pathfinding-Funktionen stellen spezifische Einschränkungen sicher, um eine effiziente Verarbeitung und optimale Erfüllungzu gewährleisten.
Vertikalplatzierungslimit
Pathfindung-Berechnungen betrachten nur Teile innerhalb bestimmter vertikaler Grenzen:
- Unterer Grenze — Teile mit einem unteren Y -Koordinaten weniger als -65,536 Studs sind ignoriert.
- Oberer Grenze — Teile mit einer oberen Y -Koordination, die 65.536 Studs überschreiten, werden ignoriert.
- VertikalSpan — Die vertikale Distanz von der untersten Teilseite Y Coordinate bis zur höchsten Teilseite Y Coordinate muss nicht 65.536 Studs überschreiten; sonst wird das Pfadfindungssystem diese Teile während der Pfadfindungsberechnung ignorieren.
Suchdistanzeinschränkung
Die direkte Sichtweite für die Wegfindung vom Anfang bis zum Ziel muss nicht 3.000 Studs überschreiten. Überschreiten dieser Distance wird ein NoPath Status ergeben.
Wege erstellen
Pathfinding wird durch PathfindingService und seine CreatePath() Funktion initiiert.
Lokales Skript
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath()
CreatePath() akzeptiert eine optionale Tabelle von Parametern, mit denen die Figur (Agent) entlang des Weges schneller wird.
Schlüssel | Beschreibung | Typ | Standard |
---|---|---|---|
AgentRadius | Agentenradius, in Studs. Nützlich für die Bestimmung der minimalen Trennung von Hindernissen. | ganzzahlig | 2 |
AgentHeight | Agentenhöhe, in Studs. Leerer Raum kleiner als dieses Wert, wie der unter dem Treppenraum, wird als nicht durchquerenbar markiert. | ganzzahlig | 5 |
AgentCanJump | Bestimmt, ob das Springen während des Wegfindungsprozesses erlaubt ist. | boolean | true |
AgentCanClimb | Bestimmt, ob das Klettern von TrussParts während der Wegfindung erlaubt ist. | boolean | false |
WaypointSpacing | Platzierung zwischen Intervalldiagrammen in path. Wenn auf math.huge festgelegt, gibt es keine Intervalldiagramme. | nummer | 4 |
Costs | Tabelle von Materialien oder definierten PathfindingModifiers und deren Kosten für die traversal. Nützlich für das Machen des Agenten bevorzugte Materialien/Regionen über andere. Siehe Modifikatoren für Details. | tabelle | nil |
Lokales Skript
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath({AgentRadius = 3,AgentHeight = 6,AgentCanJump = false,Costs = {Water = 20}})
Beachten Sie, dass der Agent während der Pathfindung TrussParts klettern kann, wenn Sie AgentCanClimb auf true setzen, wenn Sie den Pfad erstellen, und nichts blockiert den Agenten auf dem Kletterpfad. Ein kletterbares Pfad hat das
Lokales Skript - Truss Climbing Pfad
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath({AgentCanClimb = true,Costs = {Climb = 2 -- Kosten des Kletterpfades; Standard ist 1}})
Entlang von Wegen bewegen
Dieser Abschnitt verwendet das folgende Wegfindungsskript für den Charakter des Spieler:in. Um zu testen, während Sie lesen:
- Kopiere den Code in ein LocalScript innerhalb von StarterCharacterScripts .
- Bearbeite Zeile 11 zu einer Vector3 Ziel, die der Spieler-Charakter erreichen kann.
- Folgen Sie den folgenden Abschnitten, um sich über den Wegberechnungs- und Charakterbewegungsmechanismus zu informieren.
Lokales Skript - Charakter-Wegfindung
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)
-- Berechnen Sie den Pfad
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Holen Sie sich die Wegpunkte-ID
waypoints = path:GetWaypoints()
-- Blockiert den Weg, wenn er blockiert wird
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Überprüfen Sie, ob das Hindernis weiter down the path
if blockedWaypointIndex >= nextWaypointIndex then
-- Stoppen Sie die Erkennung von Blockaden auf dem Weg, bis der Weg erneut berechnet ist
blockedConnection:Disconnect()
-- Funktion aufrufen, um den neuen Weg erneut zu berechnen
followPath(destination)
end
end)
-- Erkennen, wenn die Bewegung zum nächsten Wegpunkt abgeschlossen ist
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- Erhöhen Sie den Wegpunkt-Index und bewegen Sie sich zum nächsten Wegpunkt
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- Bewegen Sie sich anfangs zum zweiten Wegpunkt (der erste Wegpunkt ist der starten; überspringen Sie ihn)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
followPath(TEST_DESTINATION)
Den Pfadberechnen
Nachdem du einen gültigen Pfad mit CreatePath() erstellt hast, muss er berechnet werden, indem du Path:ComputeAsync() aufrufst, mit einem 1> Datatype.Vector31> für den Startpunkt und die Zielperson.
Lokales Skript - Charakter-Wegfindung
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)
-- Berechnen Sie den Pfad
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
end
Waypoints erhalten
Sobald die Path berechnet ist, enthält sie eine Reihe von Wegpunkten , die den Weg vom Anfang bis zum beendenverfolgen. Diese Punkte können mit der Funktion Path:GetWaypoints() gesammelt werden.
Lokales Skript - Charakter-Wegfindung
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)
-- Berechnen Sie den Pfad
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Holen Sie sich die Wegpunkte-ID
waypoints = path:GetWaypoints()
end
end
Weg Bewegen
Jeder Wegpunkt besteht aus sowohl einer Position ( Vector3 ) als auch einer Aktion ( 2>Class.Humanoid.MoveTo2> ).
Lokales Skript - Charakter-Wegfindung
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)
-- Berechnen Sie den Pfad
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Holen Sie sich die Wegpunkte-ID
waypoints = path:GetWaypoints()
-- Blockiert den Weg, wenn er blockiert wird
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Überprüfen Sie, ob das Hindernis weiter down the path
if blockedWaypointIndex >= nextWaypointIndex then
-- Stoppen Sie die Erkennung von Blockaden auf dem Weg, bis der Weg erneut berechnet ist
blockedConnection:Disconnect()
-- Funktion aufrufen, um den neuen Weg erneut zu berechnen
followPath(destination)
end
end)
-- Erkennen, wenn die Bewegung zum nächsten Wegpunkt abgeschlossen ist
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- Erhöhen Sie den Wegpunkt-Index und bewegen Sie sich zum nächsten Wegpunkt
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- Bewegen Sie sich anfangs zum zweiten Wegpunkt (der erste Wegpunkt ist der starten; überspringen Sie ihn)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
Blockierte Wege behandeln
Viele Roblox-Welten sind dynamisch; Teile können sich bewegen oder fallen und Böden können zusammenbrechen. Dies kann einen berechenbaren Pfad blockieren und den Charakter daran hindern, sein Ziel zu erreichen. Um dies zu verhandeln, können Sie das Ereignis Path.Blocked verbinden und den Pfad um alles blockieren, was ihn blockiert.
Lokales Skript - Charakter-Wegfindung
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)
-- Berechnen Sie den Pfad
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Holen Sie sich die Wegpunkte-ID
waypoints = path:GetWaypoints()
-- Blockiert den Weg, wenn er blockiert wird
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Überprüfen Sie, ob das Hindernis weiter down the path
if blockedWaypointIndex >= nextWaypointIndex then
-- Stoppen Sie die Erkennung von Blockaden auf dem Weg, bis der Weg erneut berechnet ist
blockedConnection:Disconnect()
-- Funktion aufrufen, um den neuen Weg erneut zu berechnen
followPath(destination)
end
end)
end
end
Wegfindungs-Modifikatoren
Standardmäßig gibt Path:ComputeAsync() den kürzesten Weg zwischen dem Startpunkt und dem Ziel zurück, mit der Ausnahme, dass es versucht, Sprünge zu vermeiden. Dies sieht in einigen Situationen unnatürlich aus, z. B. ein Weg durch Wasser geht, da der Weg durch Wasser geometrisch kürzer ist.
Um den Wegfindungsprozess weiter zu optimieren, können Sie Wegfindungsmodifikatoren implementieren, um intelligente Wege über verschiedene Materialien , umgebene Regionen oder durch 1>Barrieren1> zu berechnen.
Materialienpreise einstellen
Wenn Sie mit Terrain und BasePart Materialien arbeiten, können Sie eine Costs Tabelle innerhalb von 1> Class.PathfindingService:CreatePath()|CreatePath() hinzufügen, um bestimmte Materialien mehr durchsch
Die Schlüssel in der Costs Tabelle sollten string-Namen sein, die Enum.Material Namen repräsentieren, z. B. Water für 1> Enums.Material.Water1> .
Lokales Skript - Charakter-Wegfindung
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}})
Mit Regionen arbeiten
In einigen Fällen ist Materialpräferenz nicht genug. Zum Beispiel möchten Sie, dass die Charaktere eine definierte Region vermeiden, unabhängig von den Materialien unterhalb. Dies kann durch das Hinzufügen eines PathfindingModifier -Objekts zu einem Teil erreicht werden.
Erstellen Sie ein Anchored Teil um die gefährliche Region und setzen Sie seine CanCollide Eigenschaft auf falsch .
Fügen Sie eine PathfindingModifier Instanz auf das Teil ein, finden Sie seine Label Eigenschaftenund zuweisen Sie einen Bedeutungsvollen Namen wie DangerZone zu.
Beinhalten Sie eine Costs Tabelle innerhalb von CreatePath(), die einen entsprechenden Schlüssel und die zugeordnete Zahlwert enthält. Ein Modifikator kann durch Änderung seines Wertes als nicht-traversbar definiert werden, indem seine Einstellung auf math.huge festgelegt wird.
Lokales Skript - Charakter-Wegfindunglocal PathfindingService = game:GetService("PathfindingService")local Players = game:GetService("Players")local RunService = game:GetService("RunService")local path = PathfindingService:CreatePath({Costs = {DangerZone = math.huge}})
Hindernisse ignorieren
In einigen Fällen ist es nützlich, durch solide Hindernisse zu durchkommen, als wären sie nicht vorhanden. Dies ermöglicht es Ihnen, einen Weg durch bestimmte physische Blocker zu berechnen, anstatt die Berechnung auszuführen.
Erstellen Sie ein Anchored Teil um das Objekt und setzen Sie seine CanCollide Eigenschaft auf falsch .
Fügen Sie eine PathfindingModifier Instanz auf das Teil ein und aktivieren Sie seine PassThrough Eigenschaften.
Jetzt, wenn ein Weg von dem Zombie-NPC zum Spieler-Charakter berechnet wird, verlängert sich der Weg darüber hinaus, und Sie können den Zombie auffordern, ihn zu überqueren. Selbst wenn der Zombie die Tür nicht öffnen kann, reagiert er, als ob er den Charakter hinter der Tür "hört".
Wegfindungs-Links
Manchmal ist es notwendig, einen Weg über einen Bereich zu finden, der nicht normalerweise durchqueren kann, wie z. B. über einen Graben und durchführen Sie eine benutzerdefinierte Aktion, um den nächsten Wegpunkt zu erreichen. Dies kann durch das PathfindingLink-Objekt erreicht werden.
Das obige Beispiel verwendend, können Sie den Agenten ein Boot verwenden, anstatt über alle Brücken zu gehen.
Um einen PathfindingLink mit diesem Beispiel zu erstellen:
Um die Visualisierung und das Debuggen zu unterstützen, schalten Sie Pfadfindungs-Links aus dem Visualisierungsoptionen-Podcast in der oberen rechten Ecke des 3D-Ansichtsfensters um.
Erstellen Sie zwei Attachments, eines auf dem Bootssitz und eines in der Nähe des Bootes.
Erstellen Sie ein PathfindingLink Objekt im Arbeitsbereich und weisen Sie seine Attributen Attachment0 und Attachment1 an die Start- und Endverbindungen an.
Weise dem Namen wie UseBoat eine Bedeutung wie Label zu. Dieser Name wird als Flagge im Pathfinding-Skript verwendet, um eine benutzerdefinierte Aktion auszulösen, wenn der Agent den Start-Link-Punkt erreicht.
Fügen Sie eine Costs Tabelle innerhalb von CreatePath() mit einem Water-Schlüssel und einem benutzerdefinierten Schlüssel, der den 2>Class.PathfindingLink.Label|Label2>-Eigenschaftsnamen entspricht, zu. Weisen Sie dem benutzerdefinierten Schlüssel einen niedrigeren Wert als <
Lokales Skript - Charakter-Wegfindunglocal PathfindingService = game:GetService("PathfindingService")local Players = game:GetService("Players")local RunService = game:GetService("RunService")local path = PathfindingService:CreatePath({Costs = {Water = 20,UseBoat = 1}})Im Fall eines Ereignisses, das auf einen Waypoint ausgelöst wird, fügen Sie einen benutzerdefinierten Check für den Label-Modifikatornamen hinzu und nehmen Sie eine andere Aktion als Humanoid:MoveTo() — in diesem Fall rufen Sie eine Funktion auf, um den Agenten auf dem Boot zu setzen, das Boot über das Wasser zu bewegen und den Weg des Agenten bei der
Lokales Skript - Charakter-Wegfindunglocal 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)-- Berechnen Sie den Pfadlocal success, errorMessage = pcall(function()path:ComputeAsync(character.PrimaryPart.Position, destination)end)if success and path.Status == Enum.PathStatus.Success then-- Holen Sie sich die Wegpunkte-IDwaypoints = path:GetWaypoints()-- Blockiert den Weg, wenn er blockiert wirdblockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)-- Überprüfen Sie, ob das Hindernis weiter down the pathif blockedWaypointIndex >= nextWaypointIndex then-- Stoppen Sie die Erkennung von Blockaden auf dem Weg, bis der Weg erneut berechnet istblockedConnection:Disconnect()-- Funktion aufrufen, um den neuen Weg erneut zu berechnenfollowPath(destination)endend)-- Erkennen, wenn die Bewegung zum nächsten Wegpunkt abgeschlossen istif not reachedConnection thenreachedConnection = humanoid.MoveToFinished:Connect(function(reached)if reached and nextWaypointIndex < #waypoints then-- Erhöhen Sie den Wegpunkt-Index und bewegen Sie sich zum nächsten WegpunktnextWaypointIndex += 1-- Verwenden Sie das Boot, wenn das Schild "UseBoat" ist; sonst bewegen Sie sich zum nächsten Schiffif waypoints[nextWaypointIndex].Label == "UseBoat" thenuseBoat()elsehumanoid:MoveTo(waypoints[nextWaypointIndex].Position)endelsereachedConnection:Disconnect()blockedConnection:Disconnect()endend)end-- Bewegen Sie sich anfangs zum zweiten Wegpunkt (der erste Wegpunkt ist der starten; überspringen Sie ihn)nextWaypointIndex = 2humanoid:MoveTo(waypoints[nextWaypointIndex].Position)elsewarn("Path not computed!", errorMessage)endendfunction useBoat()local boat = workspace.BoatModelhumanoid.Seated:Connect(function()-- Starte das Boot, wenn der Agent sitztif humanoid.Sit thentask.wait(1)boat.CylindricalConstraint.Velocity = 5end-- Erfassen Sie die Position des Einschränkungsvorbehalts in Bezug auf die Insellocal boatPositionConnectionboatPositionConnection = RunService.PostSimulation:Connect(function()-- Stoppen Sie das Boot, wenn Sie neben der Insel sindif boat.CylindricalConstraint.CurrentPosition >= 94 thenboatPositionConnection:Disconnect()boat.CylindricalConstraint.Velocity = 0task.wait(1)-- Unseat Agent und weiter zu Zielorthumanoid.Sit = falsehumanoid:MoveTo(waypoints[nextWaypointIndex].Position)endend)end)endfollowPath(TEST_DESTINATION)
Kompatibilität mit Streaming
In-Experience-Instanz-Streaming ist eine mächtige Funktion, die 3D-Inhalte als Charakter eines Spieler:indynamisch laden und entladen, während er um die Welt fährt. Während sie den Platzerkunden, können neue Untersets des Raumstraums auf ihrem Gerät und einige der vorhandenen Untersets möglicherweise abgestreamt werden.
Betrachte die folgenden Best Practices für die Verwendung von PathfindingService in Streaming-aktivierten Erlebnissen:
Das Streaming kann einen bestimmten Pfad blockieren oder entblocken, während ein Charakter entlang eines bestimmten Pfades läuft. Zum Beispiel, während ein Charakter durch einen Wald läuft, könnte ein Baum in irgendeinem Zeitpunkt vor ihnen auftauchen und den Pfad blockieren. Um den Wegfindungsworkflow mit dem Streaming reibungslos zu machen, wird dringend empfohlen, die Handling Blocked Paths Technik zu verwenden und den Pfad zu berechnen, wenn nötig.
Ein häufiger Ansatz bei der Wegfindung ist es, die Koordinaten von bestehenden Objekten für Berechnungen zu verwenden, z. B. das Festlegen eines Pfadziels auf die Position eines bestehenden Schatztruhes
Um dieses Problem zu beheben, berücksichtigen Sie, die Zielposition in eine BasePart innerhalb eines persistenten Modells zu setzen. Persistente Modelle laden bald nach dem Beitritt des Spielers und sie streamen nie aus, sodass ein Client-seitiges Skript sich mit dem Class.Arbeitsbereich.PersistentLoaded|PersistentLoaded -Ereignis verbinden und sicher auf das Modell zugreifen kann, nachdem das E