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.

Використання NavigationPath QueryObjects

Порада

Параметри запиту шляху надають різні опції для покращення продуктивності пошуку шляху або зменшення споживання пам'яті.

Вони задовольняють більш складні потреби пошуку шляху, які вузли високого рівня не завжди можуть задовольнити.

Дивіться відповідні розділи опцій нижче.

NavigationPathQueryObjects можна використовувати разом з NavigationServer.query_path() для отримання сильно налаштованого шляху навігації, включаючи додаткові метадані про шлях.

Це вимагає додаткових налаштувань порівняно з отриманням звичайного NavigationPath, але дозволяє адаптувати пошук шляху та надані дані шляху до різних потреб проекту.

Об'єкти NavigationPathQueryObjects складаються з пари об'єктів: об'єкта NavigationPathQueryParameters, що містить параметри налаштування для запиту, та об'єкта NavigationPathQueryResult, який отримує (регулярні) оновлення з результуючим шляхом та метаданими із запиту.

2D і 3D версії NavigationPathQueryParameters доступні як NavigationPathQueryParameters2D і NavigationPathQueryParameters3D відповідно.

2D і 3D версії NavigationPathQueryResult доступні як NavigationPathQueryResult2D і NavigationPathQueryResult3D відповідно.

Створення базового запиту шляху

Обидва параметри та результат використовуються як пара з функцією NavigationServer.query_path().

Щодо доступних параметрів налаштування, див. далі. Також див. описи кожного параметра в довіднику класу.

Хоча це не є суворою вимогою, обидва об'єкти призначені для створення один раз заздалегідь, збереження в постійній змінній для агента та повторного використання для кожного запиту шляху подальших дій з оновленими параметрами.

Повторне використання тих самих об'єктів покращує продуктивність під час частого створення об'єктів або виділення пам'яті.

Наведений нижче скрипт створює об'єкти та надає функцію query_path() для створення нових шляхів навігації. Отриманий шлях ідентичний використанню NavigationServer.map_get_path() під час повторного використання об'єктів.

extends Node2D

# Prepare query objects.
var query_parameters := NavigationPathQueryParameters2D.new()
var query_result := NavigationPathQueryResult2D.new()

func query_path(p_start_position: Vector2, p_target_position: Vector2, p_navigation_layers: int = 1) -> PackedVector2Array:
    if not is_inside_tree():
        return PackedVector2Array()

    var map: RID = get_world_2d().get_navigation_map()

    if NavigationServer2D.map_get_iteration_id(map) == 0:
        # This map has never synced and is empty, no point in querying it.
        return PackedVector2Array()

    query_parameters.map = map
    query_parameters.start_position = p_start_position
    query_parameters.target_position = p_target_position
    query_parameters.navigation_layers = p_navigation_layers

    NavigationServer2D.query_path(query_parameters, query_result)
    var path: PackedVector2Array = query_result.get_path()

    return path

Параметри постобробки шляху

Різниця в постобробці шляху залежно від макета полігона навігаційної сітки

Різниця в постобробці шляху залежно від макета полігона навігаційної сітки.

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

Цей необроблений шлях коридору полігону "пошуку" не дуже оптимізований і зазвичай погано підходить для переміщення агентів. Наприклад, найближча точка краю на полігоні навігаційної сітки може призвести до значного об'їзду для агентів на більших полігонах. Для покращення якості шляхів, що повертаються запитом, існують різні опції path_postprocessing.

  • Постообробка PATH_POSTPROCESSING_CORRIDORFUNNEL скорочує шляхи, обводячи їх навколо кутів всередині доступного коридору полігону.

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

  • Постообробка PATH_POSTPROCESSING_EDGECENTERED змушує всі точки шляху розміщуватися посередині перетнутих ребер полігону всередині доступного коридору полігону.

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

  • Постобробка PATH_POSTPROCESSING_NONE повертає шлях таким, яким він пролягав всередині доступного коридору полігону.

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

Спрощення шляху

Порада

Спрощення шляху може допомогти керувати агентами або агентами, які тремтять на тонких ребрах полігонів.

Різниця точок шляху зі спрощенням шляху або без нього

Різниця точок шляху зі спрощенням шляху або без нього.

Якщо увімкнено параметр simplify_path, до шляху застосовується варіант алгоритму спрощення шляху Рамера-Дугласа-Пойкера. Цей алгоритм випрямляє шляхи, видаляючи менш релевантні точки шляху залежно від використаного параметра simplify_epsilon.

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

Спрощення шляху також допомагає «керувати» агентами, оскільки вони мають прагнути лише до більш критичних кутових точок шляху.

Попередження

Спрощення шляху – це додаткова остаточна постобробка шляху. Воно додає додаткових витрат на продуктивність запиту, тому вмикайте його лише тоді, коли це дійсно необхідно.

Примітка

Спрощення шляху доступне на NavigationServer як узагальнена функція. Її також можна використовувати поза навігаційними запитами для всіх видів масивів позицій.

Метадані шляху

Порада

Вимкнення непотрібних параметрів метаданих шляху може покращити продуктивність і зменшити споживання пам'яті.

Запит шляху може повертати додаткові метадані для кожної точки шляху.

  • Прапорець PATH_METADATA_INCLUDE_TYPES збирає масив з елементарною інформацією про власників точок, наприклад, чи належить точка до регіону або посилання.

  • Прапорець PATH_METADATA_INCLUDE_RIDS збирає масив з RIDs власників точок. Залежно від примітиву власника точки, ці RID можуть використовуватися з різними функціями NavigationServer, пов'язаними з регіонами або посиланнями.

  • Прапорець PATH_METADATA_INCLUDE_OWNERS збирає масив з ObjectID власників точок. Ці ідентифікатори об'єктів можна використовувати з @GlobalScope.instance_from_id() для отримання вузла за цим екземпляром об'єкта, наприклад, вузла NavigationRegion або NavigationLink.

За замовчуванням збираються всі метадані шляху, оскільки ці метадані можуть бути важливими для більш просунутої навігації в ігровому процесі.

  • Наприклад, щоб знати, яка точка шляху відповідає якому об'єкту або власнику вузла всередині SceneTree.

  • Наприклад, щоб дізнатися, чи є точка шляху початком чи кінцем навігаційного посилання, яке потребує скрипта захоплення.

Для найпростіших застосувань шляхів метадані не завжди потрібні. Збір метаданих шляху можна вибірково вимкнути для підвищення продуктивності та зменшення споживання пам'яті.

Виключення або включення регіонів

Порада

Регіональні фільтри можуть значно покращити продуктивність на великих навігаційних картах, розділених на регіони.

Параметри запиту дозволяють обмежити пошук шляху до певних навігаційних сіток регіону.

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

  • За замовчуванням, якщо залишити поле порожнім, включаються всі регіони запитуваної навігаційної карти.

  • Якщо до масиву excluded_regions додано регіон RID, навігаційна сітка регіону буде ігноруватися під час пошуку шляху.

  • Якщо до масиву included_regions додано регіон RID, навігаційна сітка регіону буде врахована під час пошуку шляху, а всі інші регіони, що не включені, також будуть проігноровані.

  • Якщо регіон одночасно включено та виключено, він вважається виключеним.

Фільтри регіонів дуже ефективні для продуктивності в поєднанні з фрагментами області навігації, вирівняними по сітці. Таким чином, фільтр можна налаштувати так, щоб він включав лише фрагмент початкової позиції та навколишні фрагменти, а не всю карту навігації.

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

Наступне доповнення до базового сценарію запиту шляху демонструє ідею інтеграції зіставлення фрагментів регіону з фільтрами регіону. Це не повноцінний робочий приклад.

extends Node2D

# ...

var chunk_id_to_region_rid: Dictionary[Vector2i, RID] = {}

func query_path(p_start_position: Vector2, p_target_position: Vector2, p_navigation_layers: int = 1) -> PackedVector2Array:

    # ...

    var regions_around_start_position: Array[RID] = []

    var chunk_rings: int = 1 # Increase for very small regions or more quality.
    var start_chunk_id: Vector2i = floor(p_start_position / float(chunk_size))

    for y: int in range(start_chunk_id.y - chunk_rings, start_chunk_id.y + chunk_rings):
        for x: int in range(start_chunk_id.x - chunk_rings, start_chunk_id.x + chunk_rings):
            var chunk_id: Vector2i = Vector2i(x, y)
            if chunk_id_to_region_rid.has(chunk_id):
                var region: RID = chunk_id_to_region_rid[chunk_id]
                regions_around_start_position.push_back(region)

    query_parameters.included_regions = regions_around_start_position

    # ...

Відсікання та обмеження шляху

Порада

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

Обрізання повернутих шляхів до певних відстаней

Обрізання повернутих шляхів до певних відстаней.

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

  • Властивість path_return_max_length можна використовувати для скорочення повернутого шляху до певної максимальної довжини.

  • Властивість path_return_max_radius можна використовувати для обрізання повернутого шляху всередині радіуса кола (2D) або сфери (3D) навколо початкової позиції.

Параметри запиту дозволяють обмежити пошук шляху лише до певної відстані або певної кількості пошукових полігонів. Ці опції призначені для підвищення продуктивності та безпосередньо впливають на пошук шляху.

  • Властивість path_search_max_distance можна використовувати для зупинки пошуку шляху при перевищенні цієї відстані від початкової позиції.

  • Властивість path_search_max_polygons можна використовувати для зупинки пошуку шляху під час переходу за цим номером полігону, що шукається.

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

Попередження

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