Использование NavigationLinks
NavigationLinks используются для соединения полигонов навигационной сетки из NavigationRegion2D и NavigationRegion3D на произвольных расстояниях для поиска пути.
NavigationLinks также используются для учета сокращенных путей перемещения при поиске пути посредством взаимодействия с игровыми объектами, например, лестницами, трамплинами или телепортами.
2D- и 3D-версии узлов NavigationJumplinks доступны как NavigationLink2D и NavigationLink3D соответственно.
Различные навигационные области могут соединять свои навигационные сетки без использования NavigationLink, если у них есть пересекающиеся рёбра или рёбра, находящиеся в пределах edge_connection_margin навигационной карты. Как только расстояние становится слишком большим, построение корректных соединений становится проблемой, которую могут решить NavigationLinks.
Подробнее об использовании навигационных регионов см. в документе Использование NavigationRegions. Подробнее о соединении навигационных сеток см. в документе Подключение навигационных сеток.
Элементы NavigationLinks имеют много общих свойств с NavigationRegions, например, navigation_layers. NavigationLinks добавляют единую связь между двумя точками на произвольном расстоянии в отличие от NavigationRegions, которые добавляют более локальную проходимую область с ресурсом навигационной сетки.
У NavigationLinks есть start_position и end_position, и они могут идти в обоих направлениях, если включено bidirection. При размещении навигационная ссылка соединяет полигоны навигационной сетки, ближайшие к ее start_position и end_position в пределах радиуса поиска пути.
Радиус поиска полигона можно настроить глобально в ProjectSettings в разделе navigation/2d_or_3d/default_link_connection_radius или задать для каждой навигационной карты индивидуально с помощью функции NavigationServer.map_set_link_connection_radius().
В редакторе есть отладочные маркеры для start_position и end_position. Стрелки указывают направление, в котором можно перемещаться по ссылке, а видимый радиус позиции показывает радиус поиска полигонов. Все полигоны навигационной сетки внутри сравниваются, и для соединения с ребром выбирается ближайший из них. Если в радиусе поиска не найдено ни одного подходящего полигона, навигационная ссылка отключается.
Визуальные элементы отладки ссылок можно изменить в редакторе ProjectSettings в разделе debug/shapes/navigation. Видимость отладки также можно контролировать в меню гизмо редактора 3D Viewport.
Навигационная ссылка не обеспечивает какого-либо специального перемещения по ней. Вместо этого, когда агент достигает точки ссылки, игровой код должен отреагировать (например, через триггеры области) и предоставить агенту возможность пройти по ссылке, чтобы оказаться в другой точке ссылки (например, посредством телепортации или анимации). Без этого агент будет пытаться двигаться по пути ссылки самостоятельно. В итоге получится, что агент идёт по бездонной яме вместо того, чтобы дождаться движущейся платформы, или проходит через телепорт и проходит сквозь стену.
Шаблоны сценариев навигационных ссылок
Следующий скрипт использует NavigationServer для создания новой навигационной ссылки.
extends Node2D
var link_rid: RID
var link_start_position: Vector2
var link_end_position: Vector2
func _ready() -> void:
link_rid = NavigationServer2D.link_create()
var link_owner_id: int = get_instance_id()
var link_enter_cost: float = 1.0
var link_travel_cost: float = 1.0
var link_navigation_layers: int = 1
var link_bidirectional: bool = true
NavigationServer2D.link_set_owner_id(link_rid, link_owner_id)
NavigationServer2D.link_set_enter_cost(link_rid, link_enter_cost)
NavigationServer2D.link_set_travel_cost(link_rid, link_travel_cost)
NavigationServer2D.link_set_navigation_layers(link_rid, link_navigation_layers)
NavigationServer2D.link_set_bidirectional(link_rid, link_bidirectional)
# Enable the link and set it to the default navigation map.
NavigationServer2D.link_set_enabled(link_rid, true)
NavigationServer2D.link_set_map(link_rid, get_world_2d().get_navigation_map())
# Move the 2 link positions to their intended global positions.
NavigationServer2D.link_set_start_position(link_rid, link_start_position)
NavigationServer2D.link_set_end_position(link_rid, link_end_position)
using Godot;
public partial class MyNode2D : Node2D
{
private Rid _linkRid;
private Vector2 _linkStartPosition;
private Vector2 _linkEndPosition;
public override void _Ready()
{
_linkRid = NavigationServer2D.LinkCreate();
ulong linkOwnerId = GetInstanceId();
float linkEnterCost = 1.0f;
float linkTravelCost = 1.0f;
uint linkNavigationLayers = 1;
bool linkBidirectional = true;
NavigationServer2D.LinkSetOwnerId(_linkRid, linkOwnerId);
NavigationServer2D.LinkSetEnterCost(_linkRid, linkEnterCost);
NavigationServer2D.LinkSetTravelCost(_linkRid, linkTravelCost);
NavigationServer2D.LinkSetNavigationLayers(_linkRid, linkNavigationLayers);
NavigationServer2D.LinkSetBidirectional(_linkRid, linkBidirectional);
// Enable the link and set it to the default navigation map.
NavigationServer2D.LinkSetEnabled(_linkRid, true);
NavigationServer2D.LinkSetMap(_linkRid, GetWorld2D().NavigationMap);
// Move the 2 link positions to their intended global positions.
NavigationServer2D.LinkSetStartPosition(_linkRid, _linkStartPosition);
NavigationServer2D.LinkSetEndPosition(_linkRid, _linkEndPosition);
}
}
extends Node3D
var link_rid: RID
var link_start_position: Vector3
var link_end_position: Vector3
func _ready() -> void:
link_rid = NavigationServer3D.link_create()
var link_owner_id: int = get_instance_id()
var link_enter_cost: float = 1.0
var link_travel_cost: float = 1.0
var link_navigation_layers: int = 1
var link_bidirectional: bool = true
NavigationServer3D.link_set_owner_id(link_rid, link_owner_id)
NavigationServer3D.link_set_enter_cost(link_rid, link_enter_cost)
NavigationServer3D.link_set_travel_cost(link_rid, link_travel_cost)
NavigationServer3D.link_set_navigation_layers(link_rid, link_navigation_layers)
NavigationServer3D.link_set_bidirectional(link_rid, link_bidirectional)
# Enable the link and set it to the default navigation map.
NavigationServer3D.link_set_enabled(link_rid, true)
NavigationServer3D.link_set_map(link_rid, get_world_3d().get_navigation_map())
# Move the 2 link positions to their intended global positions.
NavigationServer3D.link_set_start_position(link_rid, link_start_position)
NavigationServer3D.link_set_end_position(link_rid, link_end_position)
using Godot;
public partial class MyNode3D : Node3D
{
private Rid _linkRid;
private Vector3 _linkStartPosition;
private Vector3 _linkEndPosition;
public override void _Ready()
{
_linkRid = NavigationServer3D.LinkCreate();
ulong linkOwnerId = GetInstanceId();
float linkEnterCost = 1.0f;
float linkTravelCost = 1.0f;
uint linkNavigationLayers = 1;
bool linkBidirectional = true;
NavigationServer3D.LinkSetOwnerId(_linkRid, linkOwnerId);
NavigationServer3D.LinkSetEnterCost(_linkRid, linkEnterCost);
NavigationServer3D.LinkSetTravelCost(_linkRid, linkTravelCost);
NavigationServer3D.LinkSetNavigationLayers(_linkRid, linkNavigationLayers);
NavigationServer3D.LinkSetBidirectional(_linkRid, linkBidirectional);
// Enable the link and set it to the default navigation map.
NavigationServer3D.LinkSetEnabled(_linkRid, true);
NavigationServer3D.LinkSetMap(_linkRid, GetWorld3D().NavigationMap);
// Move the 2 link positions to their intended global positions.
NavigationServer3D.LinkSetStartPosition(_linkRid, _linkStartPosition);
NavigationServer3D.LinkSetEndPosition(_linkRid, _linkEndPosition);
}
}