Encontrar ruta es el proceso de mover un personaje por un camino lógico para llegar a un destino, evitando obstáculos y (opcionalmente) materiales peligrosos o regiones definidas.
Visualización de navegación
Para ayudar con la búsqueda de rutas y la depuración, Studio puede renderizar una malla de navegación y etiquetas modificador.Para habilitarlos, alterna en malla de navegación y modificadores de ruta desde el widget Opciones de visualización en la esquina superior derecha del ventanilla3D.

Con malla de navegación habilitada, las áreas coloreadas muestran dónde podría nadoo nadar un personaje, mientras que las áreas no coloreadas están bloqueadas.Las flechas pequeñas indican áreas que un personaje intentará alcanzar al saltar, asumiendo que estableces AgentCanJump a true cuando creas el camino.

Con modificadores de búsqueda de caminos habilitados, las etiquetas de texto indican materiales y regiones específicos que se tienen en cuenta al usar modificadores de búsqueda de caminos.

Limitaciones conocidas
Las funciones de búsqueda de caminos tienen limitaciones específicas para garantizar un procesamiento eficiente y un ejecuciónóptimo.
Límite de colocación vertical
Las calculaciones de búsqueda de caminos solo consideran partes dentro de ciertos límites verticales:
- Límite inferior — Partes con una coordenada inferior de Y menos de -65,536 tachuelas se ignoran.
- Límite superior — Partes con una coordenada superior Y que exceda los 65,536 studs se ignoran.
- Espacio vertical — La distancia vertical desde la parte inferior de la parte más baja Y coordinada hasta la parte superior de la coordinada más alta Y no debe exceder 65,536 tachuelas; de lo contrario, el sistema de búsqueda de caminos ignorará esas partes durante la búsqueda de caminos.
Limitación de distancia de búsqueda
La distancia de línea de visión directa para la búsqueda de ruta desde el punto de inicio al punto de finalización no debe exceder 3,000 studs.Exceder esta distancia resultará en un estado NoPath de exceso.
Crear rutas
La búsqueda de ruta se inicia a través de PathfindingService y su función CreatePath().
Guión local
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath()
CreatePath() acepta una tabla opcional de parámetros que refina cómo se mueve el personaje (agente) a lo largo del camino.
Clave | Descripción | Tipo | Por defecto |
---|---|---|---|
AgentRadius | Radio del agente, en studs. Útil para determinar la separación mínima de los obstáculos. | entero | 2 |
AgentHeight | Altura del agente, en studs. El espacio vacío más pequeño que este valor, como el espacio debajo de las escaleras, se marcará como no transitable. | entero | 5 |
AgentCanJump | Determina si se permite saltar durante la búsqueda de ruta. | booleno | true |
AgentCanClimb | Determina si se permite escalar TrussParts durante la búsqueda de ruta. | booleno | false |
WaypointSpacing | Espacio entre puntos de ruta intermedios en el camino. Si se establece en math.huge, no habrá puntos de ruta intermedios. | número | 4 |
Costs | Tabla de materiales o definidos PathfindingModifiers y su costo para el recorrido.Útil para hacer que el agente prefiera ciertos materiales/regiones sobre otros.Vea modificadores para detalles. | tabla | nil |
Guión local
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath({AgentRadius = 3,AgentHeight = 6,AgentCanJump = false,Costs = {Water = 20}})
Tenga en cuenta que el agente puede escalar TrussParts durante la búsqueda de ruta asumiendo que establece AgentCanClimb a true cuando crea el camino y nada bloquea al agente desde el camino de escalada de truss.Un camino escalable tiene la etiqueta Escalada y el costo para un camino escalable es 1 por defecto.

LocalScript - rutade escalada de truss
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath({AgentCanClimb = true,Costs = {Climb = 2 -- Coste del camino de escalada; el predeterminado es 1}})
Moverse por los caminos
Esta sección usa el siguiente script de búsqueda de ruta para el personaje del jugador. Para probar mientras se lee:
- Copia el código en un LocalScript dentro de StarterCharacterScripts .
- Establece la variable TEST_DESTINATION en un destino Vector3 en tu mundo 3D al que el personaje del jugador puede llegar.
- Proceda a través de las siguientes secciones para aprender acerca de la computación de rutas y el movimiento de caracteres.
LocalScript - Búsqueda de caminos de caracteres
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)
-- Calcular el camino
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Obtener los puntos de ruta
waypoints = path:GetWaypoints()
-- Detectar si el camino se bloquea
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Compruebe si el obstáculo está más abajo en el camino
if blockedWaypointIndex >= nextWaypointIndex then
-- Dejar de detectar bloqueo de ruta hasta que se vuelva a calcular el camino
blockedConnection:Disconnect()
-- Llamar función para recalcular el nuevo camino
followPath(destination)
end
end)
-- Detectar cuando el movimiento al siguiente punto de ruta esté completo
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- Aumentar el índice de puntos de ruta y moverse al siguiente punto de ruta
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- Inicialmente muévete al segundo punto de ruta (el primer punto de ruta es el iniciardel camino; saltarlo)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
followPath(TEST_DESTINATION)
Calcular el camino
Después de haber creado un camino válido con CreatePath() , debe ser calculado llamando a Path:ComputeAsync() con un Vector3 para tanto el punto de partida como el destino.
LocalScript - Búsqueda de caminos de caracteres
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)
-- Calcular el camino
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
end

Obtener puntos de ruta
Una vez que se compute el Path, contendrá una serie de puntos de ruta que rastrean el camino desde el principio hasta finalizar.Estos puntos se pueden recopilar con la función Path:GetWaypoints().
LocalScript - Búsqueda de caminos de caracteres
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)
-- Calcular el camino
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Obtener los puntos de ruta
waypoints = path:GetWaypoints()
end
end

Movimiento de ruta
Cada punto de ruta consiste en ambas posiciones () y acciones ()).Para mover un personaje que contenga un Humanoid , como un personaje típico de Roblox, la manera más fácil es llamar Humanoid:MoveTo() desde el punto de ruta a punto de ruta, usando el evento MoveToFinished para detectar cuando el personaje llega a cada punto de ruta.
LocalScript - Búsqueda de caminos de caracteres
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)
-- Calcular el camino
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Obtener los puntos de ruta
waypoints = path:GetWaypoints()
-- Detectar si el camino se bloquea
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Compruebe si el obstáculo está más abajo en el camino
if blockedWaypointIndex >= nextWaypointIndex then
-- Dejar de detectar bloqueo de ruta hasta que se vuelva a calcular el camino
blockedConnection:Disconnect()
-- Llamar función para recalcular el nuevo camino
followPath(destination)
end
end)
-- Detectar cuando el movimiento al siguiente punto de ruta esté completo
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- Aumentar el índice de puntos de ruta y moverse al siguiente punto de ruta
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- Inicialmente muévete al segundo punto de ruta (el primer punto de ruta es el iniciardel camino; saltarlo)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
Manija de rutas bloqueadas
Muchos mundos de Roblox son dinámicos; las piezas pueden moverse o caer y los pisos pueden colapsar.Esto puede bloquear un camino calculado y evitar que el personaje llegue a su destino.Para manejar esto, puedes conectar el evento Path.Blocked y recomputar el camino alrededor de lo que lo bloqueó.
LocalScript - Búsqueda de caminos de caracteres
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)
-- Calcular el camino
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Obtener los puntos de ruta
waypoints = path:GetWaypoints()
-- Detectar si el camino se bloquea
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Compruebe si el obstáculo está más abajo en el camino
if blockedWaypointIndex >= nextWaypointIndex then
-- Dejar de detectar bloqueo de ruta hasta que se vuelva a calcular el camino
blockedConnection:Disconnect()
-- Llamar función para recalcular el nuevo camino
followPath(destination)
end
end)
end
end
Modificadores de búsqueda de caminos
Por defecto, devuelve el camino más corto entre el punto de partida y el destino, con la excepción de que intenta evitar saltos.Esto parece poco natural en algunas situaciones, por instancia, un camino puede atravesar el agua en lugar de sobre un puente cercano simplemente porque el camino a través del agua es más corto geométricamente.

Para optimizar aún más la búsqueda de caminos, puedes implementar modificadores de búsqueda de caminos para calcular rutas más inteligentes a través de varios materiales , alrededor de regiones definidas , o a través de obstáculos .
Establecer costos de material
Al trabajar con Terrain y BasePart materiales, puedes incluir una tabla Costs dentro de CreatePath() para hacer que ciertos materiales sean más transitables que otros.Todos los materiales tienen un costo predeterminado de 1 y cualquier material se puede definir como no transitable al establecer su valor en math.huge .
Las claves en la tabla Costs deben ser nombres de cadenas que representan nombres Enum.Material , por ejemplo Water para Enum.Material.Water .
LocalScript - Búsqueda de caminos de caracteres
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}})
Trabajar con regiones
En algunos casos, preferencia de material no es suficiente.Por ejemplo, es posible que quieras que los personajes eviten una región definida , independientemente de los materiales que hay debajo.Esto se puede lograr agregando un objeto PathfindingModifier a una parte.
Crea una parte Anchored alrededor de la región peligrosa y establece su propiedad CanCollide en falso .
Inserte una instancia PathfindingModifier en la parte, localice su propiedad Label y asigne un nombre significativo como DangerZone .
Incluye una tabla Costs dentro de CreatePath() que contenga una clave coincidente y un valor numérico asociado.Un modificador se puede definir como no recorrible al establecer su valor en math.huge .
LocalScript - Búsqueda de caminos de caractereslocal 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}})
Ignorar obstáculos
En algunos casos, es útil encontrar el camino a través de obstáculos sólidos como si no existieran.Esto le permite calcular un camino a través de bloqueadores físicos específicos, en lugar de que la computación fallara por completo.
Crea una parte Anchored alrededor del objeto y establece su propiedad CanCollide en falso .
Inserta una instancia PathfindingModifier en la parte y habilita su propiedad PassThrough.
Ahora, cuando un camino se compone desde el NPC zombi al personaje del jugador, el camino se extiende más allá de la puerta y puedes solicitar al zombi que lo atraviese.Incluso si el zombi no puede abrir la puerta, reacciona como si "escuchara" al personaje detrás de la puerta.
Enlaces de búsqueda de caminos
A veces es necesario encontrar un camino a través de un espacio que no se puede recorrer normalmente, como a través de un abismo, y realizar una acción personalizada para llegar al siguiente punto de ruta.Esto se puede lograr a través del objeto PathfindingLink.
Usando el ejemplo de la isla de arriba, puedes hacer que el agente use un barco en lugar de caminar por todos los puentes.

Para crear un PathfindingLink usando este ejemplo:
Para ayudar con la visualización y el depurado, activa Enlaces de búsqueda de caminos desde el widget Opciones de visualización en la esquina superior derecha del ventanilla3D.
Crea dos Attachments , uno en el asiento del barco y uno cerca del punto de aterrizaje del barco.
Crea un objeto PathfindingLink en el espacio de trabajo, luego asigna sus propiedades Attachment0 y Attachment1 a los archivos de inicio y final, respectivamente.
Asigne un nombre significativo como UseBoat a su propiedad Label.Este nombre se usa como una bandera en el script de búsqueda de ruta para activar una acción personalizada cuando el agente llega al punto de enlace de inicio.
Incluye una tabla Costs dentro de CreatePath() que contenga tanto una clave Water como una clave personalizada que coincida con el nombre de la propiedad Label.Asigna la clave personalizada un valor más bajo que Water .
LocalScript - Búsqueda de caminos de caractereslocal 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}})En el evento que se activa cuando se alcanza un punto de ruta, añade un control personalizado para el nombre del modificador Label y toma una acción diferente a la de Humanoid:MoveTo() —en este caso, llamar a una función para sentar al agente en el barco, mover el barco por el agua y continuar el camino del agente al llegar a la isla de destino.
LocalScript - Búsqueda de caminos de caractereslocal 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)-- Calcular el caminolocal success, errorMessage = pcall(function()path:ComputeAsync(character.PrimaryPart.Position, destination)end)if success and path.Status == Enum.PathStatus.Success then-- Obtener los puntos de rutawaypoints = path:GetWaypoints()-- Detectar si el camino se bloqueablockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)-- Compruebe si el obstáculo está más abajo en el caminoif blockedWaypointIndex >= nextWaypointIndex then-- Dejar de detectar bloqueo de ruta hasta que se vuelva a calcular el caminoblockedConnection:Disconnect()-- Llamar función para recalcular el nuevo caminofollowPath(destination)endend)-- Detectar cuando el movimiento al siguiente punto de ruta esté completoif not reachedConnection thenreachedConnection = humanoid.MoveToFinished:Connect(function(reached)if reached and nextWaypointIndex < #waypoints then-- Aumentar el índice de puntos de ruta y moverse al siguiente punto de rutanextWaypointIndex += 1-- Use el barco si la etiqueta de punto de ruta es "UseBoat"; de lo contrario, muévete al siguiente punto de rutaif waypoints[nextWaypointIndex].Label == "UseBoat" thenuseBoat()elsehumanoid:MoveTo(waypoints[nextWaypointIndex].Position)endelsereachedConnection:Disconnect()blockedConnection:Disconnect()endend)end-- Inicialmente muévete al segundo punto de ruta (el primer punto de ruta es el iniciardel camino; saltarlo)nextWaypointIndex = 2humanoid:MoveTo(waypoints[nextWaypointIndex].Position)elsewarn("Path not computed!", errorMessage)endendfunction useBoat()local boat = Workspace.BoatModelhumanoid.Seated:Connect(function()-- Comience a mover el barco si el agente está sentadoif humanoid.Sit thentask.wait(1)boat.CylindricalConstraint.Velocity = 5end-- Detectar la posición de restricción en relación con la islalocal boatPositionConnectionboatPositionConnection = RunService.PostSimulation:Connect(function()-- Detener el barco cuando esté al lado de la islaif boat.CylindricalConstraint.CurrentPosition >= 94 thenboatPositionConnection:Disconnect()boat.CylindricalConstraint.Velocity = 0task.wait(1)-- Desactivar al agente y continuar al destinohumanoid.Sit = falsehumanoid:MoveTo(waypoints[nextWaypointIndex].Position)endend)end)endfollowPath(TEST_DESTINATION)
Compatibilidad de transmisión
La transmisión de instancias en experiencia es una característica poderosa que carga y descarga dinámicamente contenido 3D mientras el personaje de un jugador se mueve por el mundo.A medida que exploran el espacio 3D, nuevos subconjuntos del flujo de espacio se transmiten a su dispositivo y algunos de los subconjuntos existentes podrían transmitirse.
Considera las siguientes mejores prácticas para usar PathfindingService en experiencias habilitadas para el streaming:
La transmisión puede bloquear o desbloquear un camino dado a medida que un personaje se mueve por él.Por ejemplo, mientras un personaje corre por un bosque, un árbol podría transmitirse en algún lugar delante de ellos y obstruir el camino.Para que la búsqueda de rutas funcione sin problemas con el streaming, se recomienda encarecidamente que utilice la técnica de manejo de rutas bloqueadas y re compute el camino cuando sea necesario.
Un enfoque común en la búsqueda de caminos es usar las coordenadas de objetos existentes para la computación, como establecer un destino de ruta para la posición de un modelo de Cofre del Tesoro existente en el mundo.Este enfoque es totalmente compatible con el lado del servidor Scripts ya que el servidor tiene una vista completa del mundo en todo momento, pero LocalScripts y ModuleScripts que se ejecutan en el cliente pueden fallar si intentan calcular un camino a un objeto que no se transmite.
Para abordar este problema, considere establecer el destino en la posición de un BasePart dentro de un aplicación de modeladopersistente persistente.Los modelos persistentes se cargan poco después de que el jugador se una y nunca se transmiten, por lo que un script del lado del cliente puede conectarse al evento PersistentLoaded y acceder de forma segura al modelo para crear puntos de ruta después de que se active el evento.