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.

Використання NavigationPaths

Отримання NavigationPath

Шляхи навігації можна запитувати безпосередньо з NavigationServer і не потребують додаткових вузлів чи об’єктів, якщо навігаційна карта має навігаційну сітку для роботи.

Щоб отримати двовимірний шлях, використовуйте NavigationServer2D.map_get_path(map, from, to, optimize, navigation_layers).

Щоб отримати тривимірний шлях, використовуйте NavigationServer3D.map_get_path(map, from, to, optimize, navigation_layers).

Більше настроюваних запитів шляху навігації, які потребують додаткового налаштування, див. Використання NavigationPath QueryObjects.

Одним із обов’язкових параметрів для запиту є RID навігаційної карти. Для кожного ігрового світу автоматично створюється стандартна навігаційна карта. Стандартні навігаційні карти можна отримати за допомогою get_world_2d().get_navigation_map() з будь-якого вузла-спадкоємця Node2D або get_world_3d().get_navigation_map() з будь-якого вузла-спадкоємця Node3D. Другий і третій параметри – це початкова позиція та цільова позиція як Vector2 для 2D або Vector3 для 3D.

Якщо параметр optimized має значення true, позиції шляху будуть скорочені вздовж кутів багатокутників за допомогою додаткового проходу алгоритму воронки. Це добре працює для вільного переміщення по навігаційній сітці з багатокутниками різного розміру, оскільки шлях буде обіймати кути вздовж коридору багатокутника, знайденого алгоритмом A*. З маленькими клітинками алгоритм A* створює дуже вузький коридор воронки, який може створювати потворні кутові шляхи при використанні з сітками.

Якщо параметр optimized має значення false, позиції шляху будуть розміщені в центрі кожного краю багатокутника. Це добре працює для чистого руху сітки на навігаційних сітках з багатокутниками однакового розміру, оскільки шлях проходитиме через центр комірок сітки. За межами сітки через багатокутники, які часто охоплюють великі відкриті території з одним довгим краєм, це може створити шляхи з непотрібними довгими об’їздами.

extends Node2D

# Basic query for a navigation path using the default navigation map.

func get_navigation_path(p_start_position: Vector2, p_target_position: Vector2) -> PackedVector2Array:
    if not is_inside_tree():
        return PackedVector2Array()

    var default_map_rid: RID = get_world_2d().get_navigation_map()
    var path: PackedVector2Array = NavigationServer2D.map_get_path(
        default_map_rid,
        p_start_position,
        p_target_position,
        true
    )
    return path

Повернений шлях NavigationServer буде PackedVector2Array для 2D або PackedVector3Array для 3D. Це лише оптимізований для пам’яті Масив векторних позицій. Гарантовано, що всі вектори позиції всередині масиву знаходяться в NavigationPolygon або NavigationMesh. Масив шляхів, якщо він не порожній, має позицію навігаційної сітки, найближчу до початкової позиції в позиції першого індексу path[0]. Найближча доступна позиція навігаційної сітки до цільової позиції – це позиція останнього індексу path[path.size()-1]. Усі індекси між ними є точками шляху, якими актор має слідувати, щоб досягти мети, не виходячи з навігаційної сітки.

Примітка

Якщо цільова позиція знаходиться в іншій навігаційній сітці, яка не об’єднана або не з’єднана, шлях навігації приведе до найближчої можливої позиції на навігаційній сітці початкової позиції.

Наступний скрипт переміщує вузол-спадкоємець Node3D уздовж навігаційного шляху, використовуючи навігаційну карту за замовчуванням, встановлюючи цільову позицію за допомогою set_movement_target().

@onready var default_3d_map_rid: RID = get_world_3d().get_navigation_map()

var movement_speed: float = 4.0
var movement_delta: float
var path_point_margin: float = 0.5

var current_path_index: int = 0
var current_path_point: Vector3
var current_path: PackedVector3Array

func set_movement_target(target_position: Vector3):

    var start_position: Vector3 = global_transform.origin

    current_path = NavigationServer3D.map_get_path(
        default_3d_map_rid,
        start_position,
        target_position,
        true
    )

    if not current_path.is_empty():
        current_path_index = 0
        current_path_point = current_path[0]

func _physics_process(delta):

    if current_path.is_empty():
        return

    movement_delta = movement_speed * delta

    if global_transform.origin.distance_to(current_path_point) <= path_point_margin:
        current_path_index += 1
        if current_path_index >= current_path.size():
            current_path = []
            current_path_index = 0
            current_path_point = global_transform.origin
            return

    current_path_point = current_path[current_path_index]

    var new_velocity: Vector3 = global_transform.origin.direction_to(current_path_point) * movement_delta

    global_transform.origin = global_transform.origin.move_toward(global_transform.origin + new_velocity, movement_delta)