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...
使用 NavigationLink
NavigationLink 即导航链接,可以将相隔任意距离的导航网格多边形连接起来参与寻路,多边形来自 NavigationRegion2D 和 NavigationRegion3D。
NavigationLink 也可以用来实现寻路过程中需要与游戏中的对象交互才能使用的捷径,例如梯子、跳板、传送门等。
NavigationJumplink 节点的 2D 和 3D 版本分别为 NavigationLink2D 和 NavigationLink3D。
不同 NavigationRegion 的导航网格是可以相互连接的,只要这些导航网格之间存在重叠的边缘,或者距离在导航地图的 edge_connection_margin 以内,就无需借助 NavigationLink。一旦距离太远,建立有效的连接就成了个问题——NavigationLink 可以解决这个问题。
请参阅使用导航区块以了解有关导航区域使用的更多信息。请参阅连接导航网格以了解有关如何连接导航网格的更多信息。
NavigationLink 与 NavigationRegion 共享许多属性,例如 navigation_layers。与 NavigationRegion 使用导航网格资源添加更加本地的可走访区域相比,NavigationLink 能在任意距离的两个位置之间添加单一连接。
NavigationLink 有一个 start_position 和 end_position,启用 bidirectional 时可以双向导航。当放置导航链接时,它会连接搜索半径内最靠近其 start_position(起始位置)和 end_position(结束位置)的导航网格多边形,用于进行寻路。
多边形搜索半径可以在项目设置的导航/2D 或 3D/默认链接连接半径下全局配置,也可以使用 NavigationServer.map_set_link_connection_radius() 函数为每个导航地图单独设置。
start_position 和 end_position 在编辑器中都有调试标记。箭头指示链接可以通行的方向,位置的可见半径显示多边形搜索半径。内部所有的导航网格多边形都会被比较,并选择最近的多边形进行边缘连接。如果在搜索半径内未找到有效的多边形,则导航链接将被禁用。
可以在编辑器的 ProjectSettings 中的调试/形状/导航下更改链接调试视觉效果。调试的可见性也可以在编辑器 3D 视口小工具菜单中进行控制。
导航链接并不会提供沿链接移动的特殊移动。相反,代理抵达链接位置时,游戏代码需要对此作出反应(例如借助区域触发器)并为代理提供移动到链接另一端的手段(例如借助传送或动画)。不然的话,代理就会尝试让自己沿着连接移动。你可能会看到代理没有等待移动平台就在无底洞上行走,或者越过传送门之后继续往墙里走。
导航链接脚本模板
以下代码使用 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);
}
}