Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
Usando NavigationObstacles
As versões 2D e 3D dos nós NavigationObstacles estão disponíveis como NavigationObstacle2D e NavigationObstacle3D, respectivamente.
Os obstáculos de navegação têm dupla finalidade, pois podem afetar tanto a geração de malha de navegação quanto o desvio de agentes.
Com
affect_navigation_meshativado, o obstáculo afetará a malha de navegação quando ela for gerada.Com
avoidance_enabled, o obstáculo afetará os agentes de desvio.
Dica
O desvio está ativado por padrão. Se o obstáculo não for usado para desvio, desative enabled_avoidance para economizar desempenho.
Obstáculos e malha de navegação
Obstáculos de navegação afetando a geração de malha de navegação.
Para a geração de malha de navegação, os obstáculos podem ser usados para descartar partes de todas as outras geometrias de origem dentro da forma do obstáculo.
Isso pode ser usado para impedir que as malhas de navegação sejam geradas em locais indesejados, por exemplo, dentro de geometrias "sólidas" como paredes espessas ou no topo de outras geometrias que não devem ser incluídas na jogabilidade, como telhados.
Descarte de malha de navegação indesejada por obstáculos de navegação.
Um obstáculo não adiciona geometria no processo de geração, ele apenas remove geometria. Ele faz isso anulando todas as células (voxel) com geometria de origem rasterizada que estejam dentro da forma do obstáculo. Como tal, seu efeito e detalhe de forma são limitados à resolução de célula usada pelo processo de geração.
Para mais detalhes sobre o assamento de malhas de navegação veja Usando malhas de navegação.
A propriedade affect_navigation_mesh faz com que o obstáculo contribua para a geração da malha de navegação. Ele será analisado ou desanalisado como todos os outros objetos de nó em um processo de geração de malha de navegação.
A propriedade carve_navigation_mesh torna a forma imune aos deslocamentos da geração, por exemplo, o deslocamento adicionado pelo agent_radius da malha de navegação. Ela funcionará basicamente como um estêncil (stencil) e cortará a superfície da malha de navegação que já sofreu o deslocamento. Ela ainda será afetada por pós-processamentos adicionais do processo de geração, como a simplificação de arestas.
A forma e o posicionamento do obstáculo são definidos com as propriedades height e vertices, e a global_position do obstáculo. O valor do eixo y de qualquer Vector3 usado para os vértices é ignorado, pois o obstáculo é projetado em um plano horizontal plano.
Ao gerar malhas de navegação em scripts, os obstáculos podem ser adicionados de forma procedural como uma obstrução projetada. Os obstáculos não estão envolvidos na análise da geometria de origem, portanto, adicioná-los logo antes da geração é suficiente.
var obstacle_outline = PackedVector2Array([
Vector2(-50, -50),
Vector2(50, -50),
Vector2(50, 50),
Vector2(-50, 50)
])
var navigation_mesh = NavigationPolygon.new()
var source_geometry = NavigationMeshSourceGeometryData2D.new()
NavigationServer2D.parse_source_geometry_data(navigation_mesh, source_geometry, $MyTestRootNode)
var obstacle_carve: bool = true
source_geometry.add_projected_obstruction(obstacle_outline, obstacle_carve)
NavigationServer2D.bake_from_source_geometry_data(navigation_mesh, source_geometry)
Vector2[] obstacleOutline
[
new Vector2(-50, -50),
new Vector2(50, -50),
new Vector2(50, 50),
new Vector2(-50, 50),
];
var navigationMesh = new NavigationPolygon();
var sourceGeometry = new NavigationMeshSourceGeometryData2D();
NavigationServer2D.ParseSourceGeometryData(navigationMesh, sourceGeometry, GetNode<Node2D>("MyTestRootNode"));
bool obstacleCarve = true;
sourceGeometry.AddProjectedObstruction(obstacleOutline, obstacleCarve);
NavigationServer2D.BakeFromSourceGeometryData(navigationMesh, sourceGeometry);
var obstacle_outline = PackedVector3Array([
Vector3(-5, 0, -5),
Vector3(5, 0, -5),
Vector3(5, 0, 5),
Vector3(-5, 0, 5)
])
var navigation_mesh = NavigationMesh.new()
var source_geometry = NavigationMeshSourceGeometryData3D.new()
NavigationServer3D.parse_source_geometry_data(navigation_mesh, source_geometry, $MyTestRootNode)
var obstacle_elevation: float = $MyTestObstacleNode.global_position.y
var obstacle_height: float = 50.0
var obstacle_carve: bool = true
source_geometry.add_projected_obstruction(obstacle_outline, obstacle_elevation, obstacle_height, obstacle_carve)
NavigationServer3D.bake_from_source_geometry_data(navigation_mesh, source_geometry)
Vector3[] obstacleOutline =
[
new Vector3(-5, 0, -5),
new Vector3(5, 0, -5),
new Vector3(5, 0, 5),
new Vector3(-5, 0, 5),
];
var navigationMesh = new NavigationMesh();
var sourceGeometry = new NavigationMeshSourceGeometryData3D();
NavigationServer3D.ParseSourceGeometryData(navigationMesh, sourceGeometry, GetNode<Node3D>("MyTestRootNode"));
float obstacleElevation = GetNode<Node3D>("MyTestObstacleNode").GlobalPosition.Y;
float obstacleHeight = 50.0f;
bool obstacleCarve = true;
sourceGeometry.AddProjectedObstruction(obstacleOutline, obstacleElevation, obstacleHeight, obstacleCarve);
NavigationServer3D.BakeFromSourceGeometryData(navigationMesh, sourceGeometry);
Obstáculos e desvio de agentes
Para o desvio, os obstáculos de navegação podem ser usados como obstáculos estáticos ou dinâmicos para afetar os agentes controlados por desvio.
Quando usados estaticamente, os NavigationObstacles restringem os agentes controlados por desvio para fora ou para dentro de uma área definida por um polígono.
Quando usados dinamicamente, os NavigationObstacles empurram os agentes controlados por desvio em um raio ao redor deles.
Obstáculos de evasão estáticos
Um obstáculo de desvio é considerado estático quando sua propriedade vertices é preenchida com uma matriz de contorno de posições para formar um polígono.
Obstáculo estático desenhado no editor para bloquear ou conter agentes de navegação.
Os obstáculos estáticos funcionam como limites rígidos que não devem ser ultrapassados por agentes que usam desvio, por exemplo, de forma semelhante às colisões de física, mas para o desvio.
Os obstáculos estáticos definem seus limites com uma matriz de
vertices(posições) de contorno e, no caso do 3D, com uma propriedadeheightadicional.Obstáculos estáticos só funcionam para agentes que usam o modo de desvio 2D.
Os obstáculos estáticos definem, através da ordem de enrolamento (winding order) dos vértices, se os agentes são empurrados para fora ou sugados para dentro.
Obstáculos estáticos não podem mudar de posição. Eles só podem ser teletransportados (warped) para uma nova posição e reconstruídos do zero. Como resultado, os obstáculos estáticos são inadequados para usos onde a posição muda a cada quadro, pois a reconstrução constante tem um alto custo de desempenho.
Obstáculos estáticos que são teletransportados para outra posição não podem ser previstos pelos agentes. Isso cria o risco de deixar os agentes travados caso um obstáculo estático seja teletransportado em cima deles.
Quando o desvio 2D é usado em 3D, o eixo y dos vértices do Vector3 é ignorado. Em vez disso, a posição global no eixo y do obstáculo é usada como o nível de elevação. Os agentes ignorarão obstáculos estáticos em 3D que estejam abaixo ou acima deles. Isso é determinado automaticamente pela posição global no eixo y tanto do obstáculo quanto do agente como o nível de elevação, bem como por suas respectivas propriedades de altura.
Obstáculos de evasão dinâmica
Um obstáculo de desvio é considerado dinâmico quando sua propriedade radius é maior que zero.
Obstáculos dinâmicos agem como um objeto do tipo "por favor, afaste-se de mim" para agentes que usam desvio, por exemplo, semelhante a como eles evitam outros agentes.
Obstáculos dinâmicos definem seus limites com um único
radiuspara um círculo 2D ou, no caso do desvio 3D, uma forma de esfera.Obstáculos dinâmicos podem mudar de posição a cada quadro sem custo de desempenho adicional.
Obstáculos dinâmicos com uma velocidade definida podem ter seu movimento previsto pelos agentes.
Obstáculos dinâmicos não são uma forma confiável de restringir agentes em espaços cheios ou estreitos.
Embora as propriedades estáticas e dinâmicas possam estar ativas ao mesmo tempo no mesmo obstáculo, isso não é recomendado por questões de desempenho. O ideal é que, quando um obstáculo estiver se movendo, os vértices estáticos sejam removidos e, em vez disso, o raio seja ativado. Quando o obstáculo atingir a nova posição final, ele deve aumentar gradualmente o seu raio para empurrar todos os outros agentes para longe. Com espaço seguro suficiente criado ao redor do obstáculo, ele deve adicionar os vértices estáticos novamente e remover o raio. Isso ajuda a evitar que os agentes fiquem travados no obstáculo estático que aparece de repente quando o limite estático reconstruído estiver concluído.
Semelhante aos agentes, os obstáculos podem fazer uso da máscara de bits avoidance_layers. Todos os agentes com um bit correspondente em sua própria máscara de desvio evitarão o obstáculo.
Obstáculos procedurais
Novos obstáculos podem ser criados em um script sem um Nó usando o NavigationServer diretamente.
Obstáculos criados com scripts exigem pelo menos um map e uma position. Para uso dinâmico, um radius é obrigatório. Para uso estático, uma matriz de vertices é obrigatória.
# create a new "obstacle" and place it on the default navigation map.
var new_obstacle_rid: RID = NavigationServer2D.obstacle_create()
var default_map_rid: RID = get_world_2d().get_navigation_map()
NavigationServer2D.obstacle_set_map(new_obstacle_rid, default_map_rid)
NavigationServer2D.obstacle_set_position(new_obstacle_rid, global_position)
# Use obstacle dynamic by increasing radius above zero.
NavigationServer2D.obstacle_set_radius(new_obstacle_rid, 5.0)
# Use obstacle static by adding a square that pushes agents out.
var outline = PackedVector2Array([Vector2(-100, -100), Vector2(100, -100), Vector2(100, 100), Vector2(-100, 100)])
NavigationServer2D.obstacle_set_vertices(new_obstacle_rid, outline)
# Enable the obstacle.
NavigationServer2D.obstacle_set_avoidance_enabled(new_obstacle_rid, true)
// Create a new "obstacle" and place it on the default navigation map.
Rid newObstacleRid = NavigationServer2D.ObstacleCreate();
Rid defaultMapRid = GetWorld2D().NavigationMap;
NavigationServer2D.ObstacleSetMap(newObstacleRid, defaultMapRid);
NavigationServer2D.ObstacleSetPosition(newObstacleRid, GlobalPosition);
// Use obstacle dynamic by increasing radius above zero.
NavigationServer2D.ObstacleSetRadius(newObstacleRid, 5.0f);
// Use obstacle static by adding a square that pushes agents out.
Vector2[] outline =
[
new Vector2(-100, -100),
new Vector2(100, -100),
new Vector2(100, 100),
new Vector2(-100, 100),
];
NavigationServer2D.ObstacleSetVertices(newObstacleRid, outline);
// Enable the obstacle.
NavigationServer2D.ObstacleSetAvoidanceEnabled(newObstacleRid, true);
# Create a new "obstacle" and place it on the default navigation map.
var new_obstacle_rid: RID = NavigationServer3D.obstacle_create()
var default_map_rid: RID = get_world_3d().get_navigation_map()
NavigationServer3D.obstacle_set_map(new_obstacle_rid, default_map_rid)
NavigationServer3D.obstacle_set_position(new_obstacle_rid, global_position)
# Use obstacle dynamic by increasing radius above zero.
NavigationServer3D.obstacle_set_radius(new_obstacle_rid, 0.5)
# Use obstacle static by adding a square that pushes agents out.
var outline = PackedVector3Array([Vector3(-5, 0, -5), Vector3(5, 0, -5), Vector3(5, 0, 5), Vector3(-5, 0, 5)])
NavigationServer3D.obstacle_set_vertices(new_obstacle_rid, outline)
# Set the obstacle height on the y-axis.
NavigationServer3D.obstacle_set_height(new_obstacle_rid, 1.0)
# Enable the obstacle.
NavigationServer3D.obstacle_set_avoidance_enabled(new_obstacle_rid, true)
// Create a new "obstacle" and place it on the default navigation map.
Rid newObstacleRid = NavigationServer3D.ObstacleCreate();
Rid defaultMapRid = GetWorld3D().NavigationMap;
NavigationServer3D.ObstacleSetMap(newObstacleRid, defaultMapRid);
NavigationServer3D.ObstacleSetPosition(newObstacleRid, GlobalPosition);
// Use obstacle dynamic by increasing radius above zero.
NavigationServer3D.ObstacleSetRadius(newObstacleRid, 5.0f);
// Use obstacle static by adding a square that pushes agents out.
Vector3[] outline =
[
new Vector3(-5, 0, -5),
new Vector3(5, 0, -5),
new Vector3(5, 0, 5),
new Vector3(-5, 0, 5),
];
NavigationServer3D.ObstacleSetVertices(newObstacleRid, outline);
// Set the obstacle height on the y-axis.
NavigationServer3D.ObstacleSetHeight(newObstacleRid, 1.0f);
// Enable the obstacle.
NavigationServer3D.ObstacleSetAvoidanceEnabled(newObstacleRid, true);