Encontrar Caminho é o processo de mover um personagem ao longo de um caminho lógico para chegar a um destino, evitando obstáculos e (opcionalmente) materiais perigosos ou regiões definidas.
Visualização de navegação
Para ajudar com o planejamento de caminho e depuração, o Studio pode renderizar uma malha de navegação e rótulos modificadores.Para ativá-los, ative Modelo de navegação e Modificadores de busca de caminho a partir do widget Opções de visualização no canto superior direito do janela3D.

Com malha de navegação ativada, áreas coloridas mostram onde um personagem pode caminhar ou nadar, enquanto áreas não coloridas são bloqueadas.As setas pequenas indicam áreas que um personagem tentará alcançar pulando, assumindo que você defina AgentCanJump para true quando criar o caminho .

Com modificadores de busca de caminho ativados, rótulos de texto indicam materiais e regiões específicos que são levados em consideração ao usar modificadores de busca de caminho.

Limitações conhecidas
Os recursos de localização de caminho têm limitações específicas para garantir processamento eficiente e performanceotimizado.
Limite de colocação vertical
As calificações de busca de caminho consideram apenas partes dentro de certos limites verticais:
- Limite Inferior — Peças com uma coordenada inferior de Y menos de -65,536 metros são ignoradas.
- Limite superior — Peças com uma coordenada superior Y excedendo 65.536 studs são ignoradas.
- Espaço vertical — A distância vertical do lado inferior da parte mais baixa Y para o lado superior da parte mais alta Y deve não exceder 65,536 studs; caso contrário, o sistema de busca de caminho ignorará essas partes durante a busca de caminho.
Limitação de distância de busca
A distância direta de visão para o caminho desde o ponto de partida até o ponto de chegada não deve exceder 3.000 metros.Exceder essa distância resultará em um status NoPath de.
Criar caminhos
O encontramento de caminho é iniciado através de PathfindingService e sua função CreatePath().
LocalScript
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath()
CreatePath() aceita uma tabela opcional de parâmetros que refina como o personagem (agente) se move ao longo do caminho.
Chave | Descrição | Tipo | Padrão |
---|---|---|---|
AgentRadius | Raio do agente, em studs. Útil para determinar a separação mínima de obstáculos. | integral | 2 |
AgentHeight | Altura do agente, em studs. Espaço vazio menor que esse valor, como o espaço sob as escadas, será marcado como não trilável. | integral | 5 |
AgentCanJump | Determina se o pulo durante a busca de caminho é permitido. | booleano | true |
AgentCanClimb | Determina se é permitido escalar TrussParts durante a busca de caminho. | booleano | false |
WaypointSpacing | Espaçamento entre pontos de caminho intermediários no caminho. Se definido para math.huge, não haverá pontos de caminho intermediários. | número | 4 |
Costs | Tabela de materiais ou definidos PathfindingModifiers e seu custo para trânsito.Útil para fazer com que o agente prefira determinados materiais/regiões sobre outros.Veja modificadores para detalhes. | tabela | nil |
LocalScript
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath({AgentRadius = 3,AgentHeight = 6,AgentCanJump = false,Costs = {Water = 20}})
Observe que o agente pode escalar TrussParts durante o caminho de busca assumindo que você defina AgentCanClimb para true quando criar o caminho e nada bloqueia o agente do caminho de escalada da treliça.Um caminho escalável tem a etiqueta Subida e o custo para uma subida escalável é 1 por padrão.

LocalScript - Caminho de Escalada de Treliça
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath({AgentCanClimb = true,Costs = {Climb = 2 -- Custo do caminho de escalada; o padrão é 1}})
Mova-se ao longo de caminhos
Esta seção usa o seguinte script de busca de caminho para o personagem do jogador. Para testar enquanto lê:
- Copie o código em um LocalScript dentro de StarterCharacterScripts.
- Defina a variável TEST_DESTINATION para um destino Vector3 no seu mundo 3D que o personagem do jogador possa alcançar.
- Prossiga pelas seções a seguir para aprender sobre a computação de caminho e o movimento de personagens.
LocalScript - Encontro de Caminho de Personagem
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 o caminho
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Obtenha os pontos de caminho
waypoints = path:GetWaypoints()
-- Detectar se o caminho se torna bloqueado
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Verifique se o obstáculo está mais abaixo do caminho
if blockedWaypointIndex >= nextWaypointIndex then
-- Pare de detectar bloqueio de caminho até que o caminho seja recomputado
blockedConnection:Disconnect()
-- Chame a função para recalcular o novo caminho
followPath(destination)
end
end)
-- Detectar quando o movimento para o próximo waypoint estiver completo
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- Aumentar o índice de pontos de caminho e mover para o próximo pontos de caminho
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- Inicialmente mova-se para o segundo waypoint (o primeiro waypoint é o iniciardo caminho; pule-o)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
followPath(TEST_DESTINATION)
Calcular o caminho
Depois de ter criado um caminho válido com CreatePath() , deve ser calculado ao chamar Path:ComputeAsync() com um Vector3 para o ponto de partida e destino.
LocalScript - Encontro de Caminho de Personagem
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 o caminho
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
end

Obter pontos de caminho
Uma vez que o Path é calculado, ele conterá uma série de pontos de caminho que rastreiam o caminho de início a terminar/parar/sair.Esses pontos podem ser reunidos com a função Path:GetWaypoints().
LocalScript - Encontro de Caminho de Personagem
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 o caminho
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Obtenha os pontos de caminho
waypoints = path:GetWaypoints()
end
end

Movimento de caminho
Cada ponto de caminho consiste em ambas uma posição () e uma ação () ).Para mover um personagem que contém um Humanoid , como um personagem típico do Roblox, a maneira mais fácil é chamar Humanoid:MoveTo() de um ponto de caminho para o outro, usando o evento MoveToFinished para detectar quando o personagem chega a cada ponto de caminho.
LocalScript - Encontro de Caminho de Personagem
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 o caminho
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Obtenha os pontos de caminho
waypoints = path:GetWaypoints()
-- Detectar se o caminho se torna bloqueado
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Verifique se o obstáculo está mais abaixo do caminho
if blockedWaypointIndex >= nextWaypointIndex then
-- Pare de detectar bloqueio de caminho até que o caminho seja recomputado
blockedConnection:Disconnect()
-- Chame a função para recalcular o novo caminho
followPath(destination)
end
end)
-- Detectar quando o movimento para o próximo waypoint estiver completo
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- Aumentar o índice de pontos de caminho e mover para o próximo pontos de caminho
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- Inicialmente mova-se para o segundo waypoint (o primeiro waypoint é o iniciardo caminho; pule-o)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
Lidar com caminhos bloqueados
Muitos mundos do Roblox são dinâmicos; peças podem se mover ou cair e pisos podem colapsar.Isso pode bloquear um caminho computado e impedir que o personagem chegue ao destino.Para lidar com isso, você pode conectar o evento Path.Blocked e recomputar o caminho em torno de qualquer coisa que o bloqueou.
LocalScript - Encontro de Caminho de Personagem
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 o caminho
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Obtenha os pontos de caminho
waypoints = path:GetWaypoints()
-- Detectar se o caminho se torna bloqueado
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Verifique se o obstáculo está mais abaixo do caminho
if blockedWaypointIndex >= nextWaypointIndex then
-- Pare de detectar bloqueio de caminho até que o caminho seja recomputado
blockedConnection:Disconnect()
-- Chame a função para recalcular o novo caminho
followPath(destination)
end
end)
end
end
Modificadores de busca de caminho
Por padrão, Path:ComputeAsync() retorna o caminho mais curto entre o ponto de partida e o destino, com a exceção de que tenta evitar saltos.Isso parece pouco natural em algumas situações - por instância, um caminho pode passar por água em vez de sobre uma ponte próxima simplesmente porque o caminho através de água é geometricamente mais curto.

Para otimizar ainda mais a busca de caminho, você pode implementar modificadores de busca de caminho para calcular caminhos mais inteligentes através de vários materiais , ao redor de regiões definidas ou através de obstáculos .
Definir custos de materiais
Ao trabalhar com Terrain e BasePart materiais, você pode incluir uma tabela Costs dentro de CreatePath() para tornar alguns materiais mais atravessáveis do que outros.Todos os materiais têm um custo padrão de 1 e qualquer material pode ser definido como não atravessável definindo seu valor para math.huge .
Chaves na tabela Costs devem ser nomes de corda que representam nomes Enum.Material , por exemplo Water para Enum.Material.Water .
LocalScript - Encontro de Caminho de Personagem
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}})
Trabalhar com regiões
Em alguns casos, preferência de material não é suficiente.Por exemplo, você pode querer que os personagens evitem uma região definida , independentemente dos materiais embaixo.Isso pode ser alcançado adicionando um objeto PathfindingModifier a uma peça.
Crie uma peça Anchored ao redor da região perigosa e defina sua propriedade CanCollide para falso .
Insira uma instância PathfindingModifier em parte, localize sua propriedade Label e atribua um nome significativo como Zona de Perigo .
Inclua uma tabela Costs dentro de CreatePath() que contenha uma chave correspondente e um valor numérico associado.Um modificador pode ser definido como não atravessável ao definir seu valor para math.huge .
LocalScript - Encontro de Caminho de Personagemlocal 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
Em alguns casos, é útil encontrar um caminho através de obstáculos sólidos como se eles não existissem.Isso permite que você calcule um caminho através de bloqueadores físicos específicos, versus a computação falhar completamente.
Crie uma peça Anchored ao redor do objeto e defina sua propriedade CanCollide para falso .
Insira uma instância PathfindingModifier em parte e habilite sua propriedade PassThrough.
Agora, quando um caminho é computado do NPC zumbi para o personagem do jogador, o caminho se estende além da porta e você pode solicitar que o zumbi o atravesse.Mesmo que o zumbi não consiga abrir a porta, ele reage como se "ouvisse" o personagem atrás da porta.
Links de encontramento de caminho
Às vezes, é necessário encontrar um caminho através de um espaço que não pode ser normalmente percorrido, como através de um abismo, e executar uma ação personalizada para chegar ao próximo destino.Isso pode ser alcançado através do ObjetoPathfindingLink.
Usando o exemplo da ilha acima, você pode fazer com que o agente use um barco em vez de caminhar por todas as pontes.

Para criar um PathfindingLink usando este exemplo:
Para ajudar com a visualização e depuração, ative links de busca de caminho a partir do widget Opções de Visualização no canto superior direito do janela3D.
Crie dois Attachments, um no assento do barco e um perto do ponto de desembarco do barco.
Crie um objeto PathfindingLink na área de trabalho, então atribua suas propriedades Attachment0 e Attachment1 às respectivas anexos iniciais e finais, respectivamente.
Atribua um nome significativo como UseBoat à sua propriedade Label.Este nome é usado como uma bandeira no script de busca de caminho para ativar uma ação personalizada quando o agente chegar ao ponto de ligação inicial.
Inclua uma tabela Costs dentro de CreatePath() que contenha tanto uma chave Water quanto uma chave personalizada que corresponda ao nome da propriedade Label.Atribua a chave personalizada um valor inferior a Water .
LocalScript - Encontro de Caminho de Personagemlocal 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}})No evento que dispara quando um caminho for alcançado, adicione uma verificação personalizada para o nome do modificador Label e tome uma ação diferente da Humanoid:MoveTo() - neste caso, chamando uma função para sentar o agente no barco, mover o barco através da água e continuar o caminho do agente após chegar à ilha de destino.
LocalScript - Encontro de Caminho de Personagemlocal 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 o caminholocal success, errorMessage = pcall(function()path:ComputeAsync(character.PrimaryPart.Position, destination)end)if success and path.Status == Enum.PathStatus.Success then-- Obtenha os pontos de caminhowaypoints = path:GetWaypoints()-- Detectar se o caminho se torna bloqueadoblockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)-- Verifique se o obstáculo está mais abaixo do caminhoif blockedWaypointIndex >= nextWaypointIndex then-- Pare de detectar bloqueio de caminho até que o caminho seja recomputadoblockedConnection:Disconnect()-- Chame a função para recalcular o novo caminhofollowPath(destination)endend)-- Detectar quando o movimento para o próximo waypoint estiver completoif not reachedConnection thenreachedConnection = humanoid.MoveToFinished:Connect(function(reached)if reached and nextWaypointIndex < #waypoints then-- Aumentar o índice de pontos de caminho e mover para o próximo pontos de caminhonextWaypointIndex += 1-- Use o barco se a etiqueta de destino for "UseBoat"; caso contrário, mova-se para o próximo destinoif waypoints[nextWaypointIndex].Label == "UseBoat" thenuseBoat()elsehumanoid:MoveTo(waypoints[nextWaypointIndex].Position)endelsereachedConnection:Disconnect()blockedConnection:Disconnect()endend)end-- Inicialmente mova-se para o segundo waypoint (o primeiro waypoint é o iniciardo caminho; pule-o)nextWaypointIndex = 2humanoid:MoveTo(waypoints[nextWaypointIndex].Position)elsewarn("Path not computed!", errorMessage)endendfunction useBoat()local boat = Workspace.BoatModelhumanoid.Seated:Connect(function()-- Comece a mover o barco se o agente estiver sentadoif humanoid.Sit thentask.wait(1)boat.CylindricalConstraint.Velocity = 5end-- Detectar posição de restrição em relação à ilhalocal boatPositionConnectionboatPositionConnection = RunService.PostSimulation:Connect(function()-- Pare o barco quando ao lado da ilhaif boat.CylindricalConstraint.CurrentPosition >= 94 thenboatPositionConnection:Disconnect()boat.CylindricalConstraint.Velocity = 0task.wait(1)-- Desinstale o agente e continue para o destinohumanoid.Sit = falsehumanoid:MoveTo(waypoints[nextWaypointIndex].Position)endend)end)endfollowPath(TEST_DESTINATION)
Compatibilidade de streaming
O streaming de instância na experiência é uma poderosa funcionalidade que carrega e descarrega dinamicamente conteúdo 3D enquanto um personagem do jogador se move ao redor do mundo.À medida que exploram o espaço 3D, novos subconjuntos do fluxo de espaço são transmitidos para o dispositivo deles e alguns dos subconjuntos existentes podem ser transmitidos.
Considere as seguintes melhores práticas para usar PathfindingService em experiências habilitadas para streaming:
Streaming pode bloquear ou desbloquear um caminho dado à medida que um personagem se move ao longo dele.Por exemplo, enquanto um personagem corre através de uma floresta, uma árvore pode aparecer em algum lugar à frente deles e obstruir o caminho.Para que a pesquisa de caminho funcione sem problemas com streaming, é altamente recomendável que você use a técnica lidar com caminhos bloqueados e re compute o caminho quando necessário.
Uma abordagem comum na busca de caminho é usar as coordenadas de objetos existentes para cálculo , como definir um destino de caminho para a posição de um modelo de Baú do Tesouro existente no mundo.Essa abordagem é totalmente compatível com o lado do servidor Scripts pois o servidor tem visão completa do mundo o tempo todo, mas LocalScripts e ModuleScripts que são executados no cliente podem falhar se tentarem calcular um caminho para um objeto que não está sendo transmitido.
Para abordar esse problema, considere definir o destino para a posição de um BasePart dentro de um modelo persistente persistente.Modelos persistentes carregam logo após o jogador se juntar e eles nunca são transmitidos, então um script do lado do cliente pode se conectar ao evento PersistentLoaded e acessar seguramente o modelo para criar pontos de caminho após o evento disparar.