使用 NavigationLink
NavigationLink 用來將 NavigationRegion2D 和 NavigationRegion3D 中的導航網格多邊形,在任意距離下進行連接,以便尋路使用。
NavigationLink 也可用於考慮尋路時,經由與遊戲物件互動才能使用的移動捷徑,例如梯子、跳板或傳送門。
2D 與 3D 版本的 NavigationJumplinks 節點,分別為 NavigationLink2D 與 NavigationLink3D。
只要不同的 NavigationRegion 有重疊邊界,或其邊緣落在導航地圖的 edge_connection_margin 內,就可以直接連接其導航網格,不需要 NavigationLink。當距離過大,無法直接建立有效連接時,就需要使用 NavigationLink 來解決此問題。
請參考 使用 NavigationRegion 以深入了解導航區域的使用方法。如需了解如何連接導航網格,請參考 連接導覽網格。
NavigationLink 與 NavigationRegion 共享許多屬性,例如 navigation_layers。NavigationLink 用於在任意距離的兩個位置之間新增一條連接,而 NavigationRegion 則是透過導航網格資源,建立本地可通行區域。
NavigationLink 擁有 start_position 與 end_position,並且在啟用 bidirectional 時支援雙向通行。放置後,導航連結會在搜尋半徑內,連接最靠近 start_position 及 end_position 的導航網格多邊形,以供尋路使用。
多邊形搜尋半徑可於專案設定(ProjectSettings)中的 navigation/2d_or_3d/default_link_connection_radius 進行全域設定,或透過 NavigationServer.map_set_link_connection_radius() 函式,針對每個導航地圖(map)個別指定。
start_position 與 end_position 在編輯器內都會顯示除錯標記。箭頭指示該連結可通行的方向,位置的可見圓形顯示多邊形搜尋半徑。所有在圓形範圍內的導航網格多邊形都會被比較,選擇最近的作為邊界連結。如果搜尋半徑內找不到有效的多邊形,該導航連結將會被停用。
你可以在編輯器的 ProjectSettings,於 debug/shapes/navigation 下變更連結的除錯視覺效果。此外,也可以在編輯器 3D 檢視區的小工具功能表中控制除錯顯示的可見性。
導航連結本身不會提供任何特殊的移動行為。當代理角色(agent)抵達連結位置時,遊戲程式需自行處理對應行為(例如透過區域觸發器),並讓代理角色以適當方式通過連結並移動到另一端(例如利用傳送、動畫等)。否則代理角色將會直接沿著連結的路徑移動。這可能導致角色直接走過深淵(而非等待移動平台),或是直接穿越傳送門卻卡在牆內。
導航連結腳本範本
以下腳本示範如何使用 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);
}
}