1. Documentation

Nav3D Документация

1.1 Getting Started

  • Все классы ассета, необходимые вам для работы, содержатся в пространстве имен Nav3D.API.
  • Во время функционирования Nav3D создаст на сцене несколько MonoBehaviour объектов, необходимыми ему для внутреннего использования.

Эти игровые объекты создаются с флагом DontDestroyOnLoad. Сохранение менеджеров при загрузке другой сцены может быть полезно, если, например, вы используете отдельную сцену загрузки, в которой вы инициализируете Nav3D.

  • Movement of agents (Nav3DAgent) executes inside the FixedUpdate event
  • Все длительные вычислительные операции производятся средствами CPU вне главного потока.
  • Все колбеки, предоставленные в API Nav3D исполняются в главном потоке Unity.

1.1.1 Nav3DInitializer

Для использования Nav3D в игровом режиме, надо его проинициализировать.

Для этого предназначен компонент Nav3DInitializer. Создайте его на сцене, используя следующую кнопку верхнего меню:

 

На сцене появится следующий игровой объект:

Содержит следующие настройки:

  • Init On Awake – Оставьте включенным, чтобы Nav3D выполнил инициализацию в игровом режиме при выполнении события Awake.
  • Dispose On Destroy – Оставьте включенным, чтобы Nav3D почистил все свои выделенные сущности при уничтожении сцены. Если отключите, то сущности Nav3D останутся и продолжат функционирование и на следующей сцене, которая будет загружена.
  • Min Bucket Size – Минимальный размер ячеек навигационного графа. Должен быть положительным ненулевым числом. Тут поясним чуть подробнее. По сути этот параметр позволяет настраивать уровень детализации навигационного графа. Чем меньше значение параметра - тем выше детализация графа.

Все игровые агенты, которые будут искать путь при помощи Nav3D имеют свой размер, определяемый радиусом, который вы им задаете при создании. (Об этом будет рассказано чуть позже). Минимальный размер ячейки должен быть равен максимальному из радиусов агентов, это будет гарантировать, что агент сможет пройти по любому пути на графе. Если на сцене будут находиться агенты, радиус которых превосходит минимальный размер ячейки графа поиска, то возможны ситуации, когда агенты будут задевать препятствия на сцене. В будущих версиях Nav3D будет реализован поиск пути с учетом размера агента.

*If the Init On Awake and Dispose On Destroy options are disabled, it will be your responsibility to initialize and dispose Nav3D resources. For initialization you will need to call the Nav3DInitializer.Init() method, for disposal – Nav3DInitializer.Utilize(). The value of the Min Bucket Size parameter can also be set via code; to do this, use the MinBucketSize property.

1.1.2 Nav3DManager

Nav3DManager - вспомогательный static класс. Может быть полезен для проверки факта инициализации Nav3D и/или выполнения определенных действий в момент инициализации.

В нем реализованы следующие члены :

  • Свойство bool Inited, которое показывает, был ли Nav3D уже проинициализирован.
  • Событие event Action OnNav3DInit. Оно срабатывает сразу после инициализации Nav3D. Подписавшись на него вы сможете выполнить какие-либо действия с Nav3D сразу после инициализации. При подписке на ивент ваш делегат сработает моментально, в случае если инициализация уже была произведена ранее.
  • Method IsPointInsideOccupiedVolume(Vector3 _Point)Может быть полезен для определения находится ли точка в ячейке пространства, занятого каким-либо препятствием.

If you try to use public methods from Nav3D.API namespace before Nav3D is initialized, a Nav3DManagerNotInitializedException will be thrown. Any actions with Nav3D entities may be performed only after its initialization.

1.2 Nav3DObstacle

Nav3D позволяет использовать в качестве препятствий игровые объекты на сцене с компонентом MeshFilter с назначенным Mesh, либо с компонентом Terrain.

*Для препятствий, использующих MeshFilter, убедитесь, что для mesh настройках импорта включена опция “Read/Write Enabled”.

Добавьте компонент Nav3DObstacle к игровому объекту, который вы хотите сделать препятствием на сцене.

Вы увидите его инспектор:

В нем есть следующие настройки:

  • Выбор режима обработки препятствия (обработка препятствия должна выполняться после инициализации Nav3D, чтобы оно учитывалось при поиске пути и, агенты могли его обойти во время движения):
    • Runtime - препятствие будет обработано прямо во время игрового режима после инициализации Nav3D. Это может быть полезно, если препятствие генерируется во время игрового режима.
    • Load from binary - препятствие будет загружено из заранее заготовленного бинарного файла. В большинстве случаев обстановка игровой сцены известна заранее, еще до загрузки сцены и инициализации Nav3D. В таких случаях всегда имеет смысл запекать препятствия сцены в режиме редактора, а на старте сцены загружать их из бинарного файла. Загрузка из бинарного файла всегда гораздо быстрее, чем обработка препятствия непосредственно в игровом режиме (runtime).
  • Process children если включено, то для всех детей transform дерева будет совершен сбор информации о компонентах MeshFilter и Terrain. И все дети, имеющие данные компоненты, будут учтены при обработке препятствия.

* Если вы хотите, чтобы какой-либо дочерний элемент препятствия, содержащий MeshFilter либо Terrain, не учитывался при построении навигационного графа, то навесьте на него компонент Nav3DObstacleIgnoreTag .

  • Auto-update on change - если включено, то в случае изменения положения, поворота или масштаба transform компонента препятствия, будет выполняться его повторная обработка чтобы актуализировать граф поиска. (Препятствие будет сначала удалено из хранилища препятствий, затем будет повторно обработано и добавлено в него).Данная функция доступна для использования только для препятствий с выбранным Runtime режимом обработки.

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

  • Update min period(s) - как часто должно обновляться препятствие (в секундах) при включенном параметре “Update automatically on transform change”.

Для runtime-препятствий возможно их удаление/повторное добавление в хранилище прямо во время игры. Добавление происходит при срабатывании OnEnable(), удаление происходит при срабатывании OnDisable(). Соответственно, любое runtime-препятствие, созданное на сцене во время игры будет обработано и добавлено в хранилище. Если вы удалите или отключите игровой объект препятствия, то оно удалится из хранилища. Повторное включение препятствия вновь добавить его в хранилище.

1.2.1 Nav3DObstacleLoader

Для использования возможности предзапекания препятствий на сцене в режиме редактора и последующей их загрузки из бинарного файла используется компонент Nav3DObstacleLoader. Вы можете создать его на сцене, используя следующую кнопку верхнего меню:

 

На сцене появится следующий игровой объект:

 

Для всех препятствий на сцене, которые вы хотите запечь, выберите режим обработки Load from binary

 

Далее в инспекторе компонента Nav3DObstacleLoader вы сможете увидеть список всех игровых объектов с компонентом Nav3DObstacle, подлежащих запеканию.

 

Нажмите кнопку “Bake and serialize obstacles” и выберите папку в проекте для сохранения бинарного файла с запеченными данными о препятствиях на сцене.

После успешного запекания инспектор компонента Nav3DObstacleLoader примет такой вид:

 

Инспектор успешно сериализованных Nav3DObstacle будет иметь такой вид:

Теперь в игровом режиме при инициализации Nav3D навигационные графы всех запеченных препятствиях на сцене будут загружены из бинарного файла.

Есть важная особенность касающееся игровых объектов для которых включен статический батчинг. При загрузке навигационного графа из бинарного файла, Nav3DObstacleLoader пытается проверить соответствие данных в бинарном файле и текущих параметров препятствия на сцене (структура иерархии transform, поля transform компонентов, наличие валидного меша в MeshFilter, и прочее). Данная проверка нужна чтобы выкинуть исключение и тем самым уведомить пользователя, что запеченный навигационный файл стал неактуальным, поскольку препятствие было изменено после сохранения бинарного файла. В случае включенного статического батчинга для группы препятствий, валидация никогда не будет успешной, поскольку нельзя получить доступ к мешу препятствия. Так что мы добавили возможность отключения валидации. Для этого в инспекторе Nav3DObstacleLoader снимите галочку “Validate serialized data”.

1.2.2 Deeper dive into obstacles

  • Как уже было описано выше, для того чтобы препятствие было учтено при поиске пути, необходимо навесить на его игровой объект компонент Nav3DObstacle .
  • В Nav3D существует хранилище препятствий, которое используется при поиске пути. В нем хранятся навигационные графы препятствий на сцене.
  • Все операции с препятствиями (добавление или удаление) ставятся в очередь исполнения и производятся последовательно в отдельном потоке.
  • Под обработкой препятствия подразумевается построение графа проходимости (он же навигационный граф) для каждого препятствия, либо для группы препятствий, а затем добавление этого графа в хранилище препятствий.

Графы проходимости используются при поиске пути на сцене.

Итогом обработки одного препятствия, либо группы препятствий может быть один или несколько графов проходимости, не пересекающихся между собой в пространстве.

1.3 Nav3DParticularResolutionRegion

Существует возможность определять области пространства, в которых может быть задан особый минимальный размер ячеек графа поиска

Представим ситуацию, при которой подходящим минимальным размером ячейки графа поиска (разрешением) будет значение 1. При этом есть несколько тесных областей на вашей игровой сцене, где разрешение 1 не дает достаточной детализации графа проходимости. В такой ситуации можно конечно уменьшить минимальный размер ячеек графа поиска для всего пространства вашей сцены, но это повлечет увеличение времени обработки препятствий, а также увеличение среднего времени поиска пути на сцене.

Лучшим выходом в такой ситуации будет уменьшить размер ячеек графа поиска лишь в той области, где хочется увеличить детализацию графа поиска.

Для этого мы реализовали объект Nav3DParticularResolutionRegion, который позволяет задавать регион в пространстве, в котором при построении будет использован специфический минимальный размер ячеек графа поиска.

1.3.1 Nav3DParticularResolutionRegion: Usage

Для создания области с особым размером минимальных ячеек графа поиска используйте следующую кнопку верхнего меню:

Задайте появившемуся игровому объекту нужное положение на сцене. Далее в инспекторе компонента Nav3DParticularResolutionRegion настройте размеры области, а также укажите нужный минимальный размер ячеек графа поиска . Для визуализации региона включите отображение Gizmos в окне сцены.

Ниже изображен граф поиска для двух одинаковых препятствий, одно из которых находится в регионе с минимальным размером ячеек графа = 0.2. Второе находится вне региона и минимальный размер ячеек графа поиска на всей сцене задан как = 0.4.

Препятствие справа очевидно имеет более детализированный граф поиска, поскольку находится в регионе с меньшим минимальным размером ячеек.

1.3.2 Nav3DParticularResolutionRegion: Some points

  • Использование регионов разрешения подразумевается для решения задач связанных с проходимостью графа в тесных областях пространства, таких как например узкие тоннели, маленькие отверстия, сквозь которые должна быть обеспечена возможность поиска пути. Но также в таких регионах можно задавать размер минимальной ячейки графа поиска больший, чем размер установленный на всей сцене. Это может быть полезно, когда вы наоборот хотите избежать избыточной детализации графа поиска для некоторых препятствий. Избегание избыточно высокого разрешения графа поиска благоприятно скажется на общей производительности при поиске пути.
  • Октодерево является иерархической структурой, в которой размеры всех ячеек всегда кратны размеру друг друга и от уровня к уровню размер меняется с множителем два (каждый следующий уровень содержит ячейки в два раза меньше чем в предыдущем). Так что вы можете указать лишь желаемый минимальный размер ячейки. На деле реальный минимальный размер ячейки будет вычислен относительно размера указанного при инициализации Nav3D. Если например при инициализации минимальный размер был указан как 0.4, а вы указываете желаемый минимальный размер как 0.3, то фактически будет выбран размер 0.2, поскольку он должен быть уровнем ниже и получен из 0.4 делением на 2. Если же вы выберете желаемый размер как 0.7, то фактический размер будет равен 0.8, поскольку он должен быть уровнем выше и получен умножением на 2.
  • В случае если препятствие находится внутри пересечения нескольких регионов с разным минимальным размером ячеек, при обработке в качестве минимальной ячейки будет выбрано наименьшее значение из значений регионов.
  • Рекомендуем использовать регионы в качестве статических объектов, находящихся на сцене в момент обработки всех препятствий. Операция добавления/удаления региона во время игры повлечет повторную обработку тех runtime-препятствий, которые пересекаются регионом. Static-препятствия никак не отреагируют на удаление/добавление региона. Инициализация и деинициализация региона происходит по событиям OnEnable() и соответственно DoDisable() в Nav3DParticularResolutionRegion. Так что для инициализации региона можно создать его префаб на сцене, для деинициализации - сделать неактивным его GameObject, либо уничтожить его.

1.4 Nav3DPath

Класс Path предназначен для работы с путями в пространстве.

В общем случае объекты данного типа используются агентами (Nav3DAgent) при выполнении поиска пути. Но вы также можете использовать его отдельно для своих нужд

Разумеется, работа с объектами Nav3DPath возможна только после инициализации Nav3D. Подробнее читайте в разделе"Nav3DInitializer".

1.4.1 Nav3DPathfindingManager

Данный класс содержит инструменты для работы с поиском путей на сцене. few properties to manage pathfinding tasks limitations..

Для достижения необходимого уровня производительности при использовании Nav3D могут быть полезны следующие свойства:

  • public static int CurrentPathfindingTasksCount – показывает сколько параллельных задач поиска пути активны на данный момент;
  • public static int MaxPathfindingTasks – allows you to limit a number of pathfinding tasks running simultaneously. By default, this property is set to Environment.ProcessorCount - 1

1.4.2 Nav3DPath: Pathfinding

Для поиска пути необходимо: 

  1. Создать экземпляр Nav3DPath используя конструктор: new Nav3DPath().
  2. Для созданного объекта Nav3DPath вызовите один из методов:

Для поиска пути между двумя точками:

				
					public void Find(
Vector3 _Start,
Vector3 _End,
Action _OnSuccess = null,
Action<PathfindingError> _OnFail = null
)
				
			

Назначение параметров:

  • Action _OnSuccess - колбэк успешного завершения поиска пути.
  • Action<PathfindingError> _OnFail - колбек завершения поиска пути в случае ошибки, содержит данные об ошибке.

Для поиска пути между множеством точек (больше 2):

				
					public void Find(
       Vector3[] _Targets,
       bool _Loop,
       bool _SkipUnpassableTargets = false,
       Action _OnSuccess = null,
       Action<PathfindingError> _OnFail = null
   )

				
			

Назначение параметров:

  • bool _Loop - нужно ли замкнуть путь (будет найден путь между первой и последней точкой в наборе).
  • bool _SkipUnpassableTargets = false - будет ли пропускаться каждая точка, до которой поиск пути завершился с ошибкой. Если параметр установлен в false, то при неудаче поиска пути между любой парой точек, будет выполнен _OnFail колбэк, и поиск будет прекращен.

Имеется возможность повторить последний поиск пути. Это может быть полезно, если вы считаете, что последний найденный путь больше не актуален, например в случае, если изменилась конфигурация сцены (какие-либо препятствия были добавлены или удалены).

Для этого вызовите метод public void Update() .

1.4.3 Nav3DPath: Properties

  • public bool IsValid { get; } - показывает, был ли успешным последний завершенный поиск пути. Свойство примет значение false, если изменить значение одного из свойств Smooth or SmoothRatio .
  • public bool IsPathfindingInProgress { get; } - выполняется ли поиск пути в данный момент.
  • public Vector3[] Trajectory { get; } - траектория последнего найденного пути. IsValid Используйте свойство IsValid для проверки того, что значение достоверно.
  • public Bounds Bounds { get; } - объем пространства, который занят найденным путем.
  • public bool Smooth { get; set; } - нужно ли производить сглаживание пути.
  • public int SmoothRatio { get; set; } - количество проходов сглаживания по отношению к минимальному размеру ячейки графа поиска, по умолчанию установлено как 3. Не рекомендуется увеличивать это значение без необходимости, так как это увеличит время поиска пути, в случае если сглаживание включено (свойство Smooth == true).
  • public int Timeout { get; set; } - максимальное время поиска пути. В случае, если поиск пути длится дольше, произойдет выполнение колбека Action<PathfindingError> _OnFail , если он был передан в Find().
  • public bool TryRepositionStartIfOccupied { get; set; } - в случае, если для поиска пути указана стартовая точка, находящаяся в ячейке пространства, занятой препятствием, пытаться найти соседнюю свободную ячейку и осуществлять поиск из нее.
  • public bool TryRepositionTargetIfOccupied  { get; set; } - в случае, если для поиска пути указана целевая точка, находящаяся в ячейке пространства, занятой препятствием, пытаться найти соседнюю свободную ячейку и осуществлять поиск до нее.
  • public PathfindingResult { get; } - результат последнего успешного поиска пути.

1.4.4 Nav3DPath: Events

Для удобства отслеживания окончания поиска пути реализованы события:

  • public event Action OnPathfindingSuccess - срабатывает при успешном завершении поиска пути.
  • public event Action<PathfindingError> OnPathfindingFail - срабатывает при возникновении ошибки при поиске пути.
  • public event Action OnPathfindingComplete - срабатывает как при успешном, так и при неуспешном завершении поиска пути.

1.4.5 Nav3DPath: Dispose

После того как вы завершили работу с объектом Nav3DPath, необходимо вызвать метод public void Dispose(). необходимо вызвать метод public void Dispose(). Это необходимо для удаления пути из хранилища препятствий. В противном случае при добавлении/обновлении/удалении какого-либо препятствия, путь будет проверяться на необходимость обновления, что будет занимать вычислительные ресурсы. Любые пути, инициализированные на сцене, для которых не был вызван Nav3DPath , будут занимать вычислительные ресурсы.

1.4.6 PathfindingError

Содержит сведения об ошибке в случае срабатывания _OnFail колбэка.

Свойства:

  • public PathfindingResultCode Reason причина неудачи поиска пути
    Возможные значения свойства:
ValueОписание
SUCCEEDEDПоиск пути завершился успешно.
PATH_DOES_NOT_EXISTМежду точками не существует пути. Это возможно если хотя бы одна из точек окружена препятствиями со всех сторон.
TIMEOUTПоиск пути занял больше времени чем разрешено и был прерван.
CANCELEDПоиск пути был завершен по указанию пользователя, или по внутренней логике Nav3D.
START_POINT_INSIDE_OBSTACLEПоиск пути не удался, потому что начальная точка пути находится внутри препятствия
TARGET_POINT_INSIDE_OBSTACLEPathfinding has been canceled because the target point of the path is inside an obstacle.
UNKNOWNВнутренняя ошибка.
  • public string Msg сообщение с более подробной информацией об ошибке.

1.4.7 PathfindingResult

Хранит результаты поиска пути и временные затраты.

Временные затраты поиска пути:

    • public TimeSpan PathfindingDuration { get; } - длительность выполнения поиска пути (A*).
    • public TimeSpan OptimizingDuration  { get; } - длительность выполнения оптимизации пути.
    • public TimeSpan SmoothingDuration   { get; } - длительность выполнения сглаживания пути.

Результаты поиска пути:

    • public Vector3[] RawPath { get; } - найденный путь после работы алгоритма A*
    • public Vector3[] PathOptimized { get; } - путь после применения алгоритма оптимизации.
    • public Vector3[] PathSmoothed  { get; } - путь после применения алгоритма сглаживания к оптимизированному пути. Если Smooth = false, то содержимое будет идентично PathOptimized.
    • public int[] TargetIndices { get; } – the indices of the target points in the PathSmoothed array. The target points mean the points used when calling Nav3DPath.Find().
    • public PathfindingResultCode Result { get; } - код результата поиска.

1.4.8 Usage example

Ниже приведен пример использования Nav3DPath.

				
					using Nav3D.API;
using System;
using System.Linq;
using UnityEngine;

class YourGameScenario : MonoBehaviour
{
   #region Attributes

   Vector3[] m_FoundPath;

   #endregion
  
   #region Unity events

   void Start()
   {
       Nav3DManager.OnNav3DInit += () =>
       {
           Vector3 a = new Vector3(-10, -10, -10);
           Vector3 b = new Vector3(10, 10, 10);

           FindPath(a, b, PrintPath);
       };
   }

   void OnDrawGizmos()
   {
       if (!Application.isPlaying || !enabled)
           return;

       if (m_FoundPath != null && m_FoundPath.Any())
       {
           for (int i = 0; i < m_FoundPath.Length - 1; i++)
               Gizmos.DrawLine(m_FoundPath[i], m_FoundPath[i + 1]);
       }
   }
  
   #endregion

   #region Service methods

   //your method for pathfinding from A to B
   void FindPath(Vector3 _A, Vector3 _B, Action<Vector3[]> _OnPathFound)
   {
       //create Nav3DPathPath instance
       Nav3DPath path = new Nav3DPath(gameObject.name);

       //perform pathfinding from _A to _B
       path.Find(
               _A,
               _B,
               _OnSuccess: () =>
               {
                   //notify that path was found
                   Debug.Log("Path successfully found!");

                   //invoke callback
                   _OnPathFound(path.Trajectory);

                   //finish work with Nav3DPath instance
                   path.Dispose();
               }
           );
   }

   void PrintPath(Vector3[] _Path)
   {
       m_FoundPath = _Path;

       Debug.Log($"Path points: {string.Join(", ", m_FoundPath)}");
   }

   #endregion
}

				
			

1.4.9 Nav3DPathTester

Мы реализовали специальный компонент (Nav3DPathTester), который может быть использован при построении игровых сцен для проверки того, как будет проходить путь в разных местах сцены.

  • Для его использования вам надо добавить на любой игровой объект на сцене компонент Nav3DPathTester.
  • Для его работы система Nav3D должна быть инициализирована, так что его применение возможно только в игровом режиме.

После добавления компонента вы увидите его инспектор:

Здесь смысл всех параметров соответствует смыслу параметров метода Nav3DPath.Find() .

Добавьте на игровую сцену несколько игровых объектов, которые будут служить в качестве точек между которыми будет искаться путь. Далее добавьте эти объекты в список Targets в инспекторе Nav3DPathTester.

В игровом режиме, при включенном Gizmos вы сможете увидеть как путь пройдет через все объекты Targets.

Ниже показаны два примера тестового пути для трех объектов при выключенной и включенной опцией Loop.

1.5 Nav3DAgent

У Nav3DAgent это основной класс, осуществляющий движение игровых юнитов в пространстве игровой сцены.

  1. Nav3DAgent возможно только после инициализации Nav3D. Подробнее читайте в разделе Nav3DInitializer .
  2. Используйте этот класс в качестве компонента для ваших игровых юнитов.
  3. Для использования Nav3DAgent необходимо настроить его поведение. Это возможно сделать с помощью использования класса Nav3DAgentConfig.

1.5.1 Nav3DAgentManager

В этом классе доступны методы получения списка агентов на сцене, находящихся в некоторой области:

  • public static Nav3DAgent[] GetAgentsInBounds(Bounds _Bounds) - получить список агентов Nav3DAgent, находящихся в Bounds.
  • public static Nav3DAgent[] GetAgentsInSphere(Vector3 _Center, float _Radius) - получить список агентов Nav3DAgent, находящихся в сфере с центром в _Center, радиусом _Radius.

1.5.2 Nav3DAgentConfig

Nav3DAgentConfig служит описанием агента и позволяет настраивать его поведение и все необходимые параметры.

Вы можете создать экземпляр через контекстное меню вкладки Проект.

После создания описания в инспекторе вы увидите следующий список групп параметров:

Приведем пояснение назначения параметров и их допустимые величины.

Behavior

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Motion Navigation Type
MotionNavigationType
enum MotionNavigationType
COMBINED, GLOBAL, LOCAL

Основное назначение всех агентов - движение к какой-либо точке в пространстве. Агенты могут двигаться с помощью трех способов ориентирования в пространстве.

  • Используя глобальный путь (GLOBAL). В таком случае агент выполнит поиск пути и будет двигаться по нему, невзирая на внешние условия (другие агенты, находящиеся слишком близко края препятствий).
  • С использованием только локального уклонения (LOCAL). Агент не будет использовать поиск пути для движения, а будет двигаться к цели по прямой, попутно уклоняясь от других агентов и препятствий, когда они встречаются на курсе движения. Разумеется не всякое препятствие может быть преодолено таким образом.
  • Наконец, агент может осуществлять движение к цели используя поиск пути и локальное уклонение одновременно (COMBINED). Агент будет двигаться по найденному пути и уклоняться от подошедших близко других агентов, а также находящихся слишком близко препятствий.

Radius

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Radius
Radius
float
>0

Радиус агента используется для осуществления маневров локального уклонения. Установление корректного радиуса важно для эффективного выполнения локального уклонения как самим агентом, так и прочими агентами поблизости. Советуем настраивать радиус так, чтобы все визуальное содержимое игрового юнита, коим является агент, находилось внутри сферы.

Speed

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Speed
Speed
float
>0

Скорость движения агента. Можете менять ее в любой момент времени, если потребуется.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Max Speed
Max Speed
float
>Speed

Максимальная скорость агента. Этот параметр нужен для выполнения локального уклонения. В некоторых ситуациях агенту может потребоваться ускориться, чтобы избежать столкновения. Если значение будет слишком велико, то порой агент может двигаться рывками при выполнении локального уклонения. Так что советуем выставлять максимальную скорость чуть больше чем Speed(больше менее чем в полтора раза).

Для вашего удобства в инспекторе имеется два способа установления этого значения. С помощью конкретного значения. Либо с помощью множителя для Speed. Советуем использовать множитель, для того чтобы максимальная скорость зависела от Speed агента. Тогда MaxSpeed будет меняться вслед за изменением Speed

Local avoidance

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Agents considered number limit
Agents considered number limit
bool
true, false

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

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Agents number
ConsideredAgentsNumberLimit
int
>=1

Количество агентов, которые берутся в рассмотрение из всех ближайших агентов.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Avoid static obstacles
AvoidStaticObstacles
bool
true, false

Нужно ли выполнять локальное уклонение от статических препятствий

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

Не рекомендуется включать эту возможность без надобности, поскольку она оказывает нагрузку на производительность.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
ORCA Tau
ORCATau
float
>0

Временной диапазон вычисления скоростного препятствия. Не рекомендуем менять этот параметр

Лучше понять его смысл вам поможет оригинальная статья по ORCA Reciprocal n-body Collision Avoidance. Jur van den Berg, Stephen J. Guy, Ming Lin, and Dinesh Manocha

Поиск пути

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Pathfinding timeout (ms)
PathfindingTimeout
int
>0

Максимальное время, отведенное на выполнение поиска пути. При превышении этого времени поиск(pathfinding) будет отменен, и будет вызван колбек _OnPathfindingFail.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Smooth the path
SmoothPath
bool
true, false

Нужно ли сглаживать найденный путь.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Samples per min bucket volume
SmoothRatio
int
>0

Количество сегментов пути на один минимальный объем октодерева, получаемых при сглаживании исходного пути. Не следует избыточно увеличивать этот параметр, так как это увеличивает итоговое время поиска пути.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Auto-update path on stagnant behavior
AutoUpdatePath
bool
true, false

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

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

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Auto-update cooldown (ms)
PathAutoUpdateCooldown
int
>=1

Минимальный период автокорректировки пути. Если область пространства будет слишком заполнена другими агентами, то пересчет пути может быть слишком частым, что негативно повлияет на производительность в случае большого количества агентов на сцене. Рекомендуем ограничить частоту автокорректировки несколькими секундами.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Try reposition target if occupied
TryRepositionTargetIfOccupied
bool
true, false

Включение параметра позволит совершить попытку поиска пути до соседней свободной ячейки, если целевая точка оказалась в ячейке, занятой препятствием.

Если параметр выключен, тогда в таком случае поиск пути будет прерван с ошибкой GOAL_POINT_INSIDE_OBSTACLE .

Motion

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Target reach distance
TargetReachDistance
float
>=0

Расстояние достижения цели. Когда вы отдаете агенту приказание достичь какой-либо цели, цель будет считаться достигнутой, когда pivot агента совпадет с координатой цели (расстояние между ними будет равным 0). Это может быть неудобно, если целью является объект с мешем, допустим планета в космосе. В таком случае выставьте этот параметр равным сумме радиуса видимой части агента и радиуса планеты. Тогда агент остановится, достигнув поверхности планеты.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Max rotation in degrees per fixed update tick
MaxAgentDegreesRotationPerTick
float
>=0

Максимальное количество градусов, на которое может повернуться агент при выполнении поворота в сторону движения.
В процессе движения агент поворачивается в сторону вектора скорости. Если вектор скорости круто меняется в процессе движения, то поворачивание агента может выглядеть резким. Чтобы сделать его более плавным, выставите этот параметр не слишком большим.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Rotation vector lerp factor
RotationVectorLerpFactor
float
(0 - 1)

In order to make the rotation of an agent even more smoother, when computing the rotation vector the frame rotation vector and the value of rotation vector for a few last frames are used.

Decreasing the parameter makes the rotation smoother, increasing it makes it sharper.

Velocity blending

При использовании глобального поиска пути и локального уклонения агент двигается, используя три вектора скорости:

  1. Вектор скорости следования по пути.
  2. Вектор скорости уклонения от агентов.
  3. Вектор скорости уклонения от препятствий.

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

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

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

Ниже приведены пояснения для параметров весов. Обратите внимание, что для каждой ситуации используются отдельные параметры

Все веса задаются типом float и должны иметь значение более 0

Соответствующие названия свойств в Nav3DAgentConfig:

  • PathVelocityWeight
  • PathVelocityWeight1
  • PathVelocityWeight2
  • AgentsAvoidanceVelocityWeight
  • AgentsAvoidanceVelocityWeight1
  • AgentsAvoidanceVelocityWeight2
  • ObstacleAvoidanceVelocityWeight
  • ObstacleAvoidanceVelocityWeight1
  • ObstacleAvoidanceVelocityWeight2

Debug

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Use log
UseLog
bool
true, false

Нужно ли логгировать работу агента.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Log records count
LogSize
int
>0

Размер лога.

1.5.3 Nav3DAgent: Methods

Как упоминалось выше, вы можете использовать скрипт Nav3DAgent в качестве компонента для вашего игрового объекта и обращаться к нему через GetComponent() .

Для управления Nav3DAgent реализованы следующие публичные методы:

  • установка Nav3DAgentConfig.
				
					public void SetConfig(Nav3DAgentConfig _Config)
				
			
  • Команда двигаться к точке.
				
					public void MoveTo(
Vector3                  _Point,
Action                   _OnReach           = null,
Action<PathfindingError> _OnPathfindingFail = null,
float?                   _ReachDistance     = null)
				
			

Параметры:

    • Vector3 _Point - целевая точка.
    • Action _OnReach - колбэк достижения целевой точки.
    • Action<PathfindingError> _OnPathfindingFail - колбэк ошибки поиска пути.
    • float? _ReachDistance - расстояние до целевой точки, необходимое для завершения следования и срабатывания _OnFinished.
  • Команда последовательно двигаться по списку точек. Будет найден путь, проходящий через каждую точку массива.
				
					public void MoveToPoints(
Vector3[]                _Points,
bool                     _Loop                  = false,
bool                     _StartFromClosest      = false,
bool                     _SkipUnpassableTargets = false,
float?                   _ReachDistance         = null,
Action<Vector3>  _OnTargetPointPassed           = null,
Action                   _OnFinished            = null,
Action<PathfindingError> _OnPathfindingFail     = null)

				
			

Параметры:

  • Vector3[] _Points – a target points.
  • bool _Loop - замыкать ли движение по точкам. Если true, агент будет двигаться по последовательности точек бесконечно, переходя к первой каждый раз при достижении последней.
  • bool_StartFromClosest - начинать ли движение с ближайшей точки массива, а не с первой.
  • bool_SkipUnpassableTargets - будет ли пропускаться каждая точка, до которой поиск пути завершился с ошибкой. Если параметр установлен в false, то при неудаче поиска пути между любой парой точек, будет выполнен _OnFail колбэк, и поиск будет прекращен.
  • float? _ReachDistance - расстояние до целевой точки, необходимое для завершения следования и срабатывания _OnFinished.
  • Action<Vector3> _OnTargetPointPassed - колбэк, срабатывающий при прохождении агентом одной из целевых точек пути.
  • Action _OnFinished - колбэк, срабатывающий при прохождении агентом последней точки пути. Колбэк не сработает, если _Loop = true.
  • Action<PathfindingError> _OnPathfindingFail - колбэк ошибки поиска пути.
  • Начать преследование transform цели.

				
					public void FollowTarget(
Transform                _Target,
bool                     _FollowContinuously,
float                    _TargetOffsetUpdate,
float                    _TargetReachDistance   = 0,
Action                   _OnReach               = null,
Action                   _OnFail                = null,
Action<PathfindingError> _OnPathfindingFail     = null)

				
			

Параметры:

    • Transform _Target - цель для преследования.
    • bool _FollowContinuously - преследовать ли цель без окончания. Если true, то агент никогда не прекратит преследование и не вызовет _OnReach. При достижении цели просто будет находиться рядом, пока цель снова не отдалится.
    • float _TargetOffsetUpdate - величина смещения цели, для которой наступит перерасчет пути до цели.
    • float _TargetReachDistance - расстояние до transform цели, необходимое для завершения преследования и срабатывания _OnReach.
    • Action _OnReach - колбэк достижения цели преследования.
    • Action _OnFail - колбэк, срабатывающий в случае если transform цели был уничтожен или переведен в неактивное состояние на сцене.
    • Action<PathfindingError> _OnPathfindingFail - колбэк ошибки поиска пути.
  • Останавливает выполнение текущей действующей команды
				
					public void Stop()
				
			
  • Возвращает агентов, удовлетворяющих предикату, находящихся в заданном радиусе от агента.
				
					public Nav3DAgent[] GetAgentsInRadius(float _Radius, Predicate<Nav3DAgent> _Predicate = null)
				
			

Примеры по использованию Nav3DAgent вы можете найти в демо сценах, расположенных в папке Nav3D/Demo.

1.5.4 Nav3DAgent: Debug

У Nav3DAgent реализован инспектор, предоставляющий несколько полезных функций, помогающих в отладке и дающих лучшее понимание о взаимодействии объектов на сцене.

1.5.5 Nav3DEvader

Мы реализовали отдельный контроллер, поведение которого состоит в уклонении от находящихся рядом агентов, и статических препятствий, если вдруг он попал в соприкосновение с ними.

Его поведение выглядит довольно интересно, и продемонстрировано в демо Nav3D/Demo/EvadersCrowd.

В инспекторе компонента имеются следующие настройки:

  • Radius - радиус, для которого проверяется пересечение с другими агентами и прочими сущностями.
  • Max Speed - максимально возможная скорость при выполнении избегания столкновения.
  • Speed Decay Factor - множитель затухания скорости после завершения избегания. Чем больше значение, тем быстрее остановится Nav3DEvader после избегания столкновения. допустимое значение в диапазоне (0 - 1).

1.5.6 Nav3DSphereShell

Представляет собой сферическую оболочку, которая воспринимается агентами как объект для уклонения. Nav3DSphereShell может приводиться в движение извне, агенты на сцене, а также Nav3DAgents and Nav3DEvader, будут уклоняться от столкновения с ним.

Поведение Nav3DSphereShell продемонстрировано в демо Nav3D/Demo/SphereShellDemo.

В инспекторе компонента вы можете настроить радиус сферы.

2. Nav3DInitializer

Для использования Nav3D в игровом режиме, надо его проинициализировать.

Для этого предназначен компонент Nav3DInitializer. Создайте его на сцене, используя следующую кнопку верхнего меню:

 

На сцене появится следующий игровой объект:

Содержит следующие настройки:

  • Init On Awake – Оставьте включенным, чтобы Nav3D выполнил инициализацию в игровом режиме при выполнении события Awake.
  • Dispose On Destroy – Оставьте включенным, чтобы Nav3D почистил все свои выделенные сущности при уничтожении сцены. Если отключите, то сущности Nav3D останутся и продолжат функционирование и на следующей сцене, которая будет загружена.
  • Min Bucket Size – Минимальный размер ячеек навигационного графа. Должен быть положительным ненулевым числом. Тут поясним чуть подробнее. По сути этот параметр позволяет настраивать уровень детализации навигационного графа. Чем меньше значение параметра - тем выше детализация графа.

Все игровые агенты, которые будут искать путь при помощи Nav3D имеют свой размер, определяемый радиусом, который вы им задаете при создании. (Об этом будет рассказано чуть позже). Минимальный размер ячейки должен быть равен максимальному из радиусов агентов, это будет гарантировать, что агент сможет пройти по любому пути на графе. Если на сцене будут находиться агенты, радиус которых превосходит минимальный размер ячейки графа поиска, то возможны ситуации, когда агенты будут задевать препятствия на сцене. В будущих версиях Nav3D будет реализован поиск пути с учетом размера агента.

*If the Init On Awake and Dispose On Destroy options are disabled, it will be your responsibility to initialize and dispose Nav3D resources. For initialization you will need to call the Nav3DInitializer.Init() method, for disposal – Nav3DInitializer.Utilize(). The value of the Min Bucket Size parameter can also be set via code; to do this, use the MinBucketSize property.

3. Operations with obstacles

Вне зависимости от режима обработки препятствий процедура обработки состоит из нескольких этапов:

  1. Сбор информации о геометрии препятствия для каждого Nav3DObstacle.

    На данном этапе происходит получение списка всех геометрий, образующих препятствие, затем происходит их объединение (кластеризация).

    Положим, в transform иерархии препятствия есть несколько дочерних элементов, у каждого из которых есть MeshFilter с назначенным Mesh. Соответственно, в таком случае будет получено несколько списков треугольников, из которых состоят меши. Далее для каждого списка треугольников будет определен охватывающий объем в виде Bounds. Те списки, чьи Bounds пересекаются, будут объединены. Будем называть каждый такой отдельный список “объемом препятствия”. В результате получается один или несколько объемов препятствий. Это будет проделано для каждого обрабатываемого Nav3DObstacle на сцене.

  2. Кластеризация с уже обработанными препятствиями.

    Проверяется, пересекает(-ют) ли объемы добавляемого препятствия с объемами уже находящихся в хранилище препятствий. Если да, то происходит кластеризация с уже добавленными препятствиями. В результате получается новый список объемов препятствий.

  3. Удаление из хранилища неактуальных объемов хранимых препятствий

    Не актуальными считаются те объемы, которые пересеклись с объемами вновь добавляемого препятствия, и которые вошли с состав новых (кластеризованных) объемов.

  4. Далее происходит построение графов проходимости для новых объемов, затем эти объемы (вместе с графом внутри) добавляются в хранилище препятствий. navigation graphs are constructed for new volumes.

    These volumes are then added to the obstacle storage.

Удаление препятствия из хранилища состоит из следующих этапов:

  1. Из хранилища получается список всех объемов, содержащих треугольники удаляемого препятствия (в каждом объеме могут быть треугольники нескольких препятствий).
  2. Для каждого объема из полученного списка происходит удаление треугольников удаляемого препятствия.
  3. Далее рассматриваются только объемы, в которых после изъятия еще остались треугольники. Для этих объемов пересчитываются ограничивающие Bounds.
  4. Все объемы из первоначального списка удаляются из хранилища препятствий.
  5. Все оставленные объемы с пересчитанными Bounds кластеризуются и вновь добавляются в хранилище препятствий.

4. Getting Started

  • Все классы ассета, необходимые вам для работы, содержатся в пространстве имен Nav3D.API.
  • Во время функционирования Nav3D создаст на сцене несколько MonoBehaviour объектов, необходимыми ему для внутреннего использования.

Эти игровые объекты создаются с флагом DontDestroyOnLoad. Сохранение менеджеров при загрузке другой сцены может быть полезно, если, например, вы используете отдельную сцену загрузки, в которой вы инициализируете Nav3D.

  • Movement of agents (Nav3DAgent) executes inside the FixedUpdate event
  • Все длительные вычислительные операции производятся средствами CPU вне главного потока.
  • Все колбеки, предоставленные в API Nav3D исполняются в главном потоке Unity.

4.1 Nav3DInitializer

Для использования Nav3D в игровом режиме, надо его проинициализировать.

Для этого предназначен компонент Nav3DInitializer. Создайте его на сцене, используя следующую кнопку верхнего меню:

 

На сцене появится следующий игровой объект:

Содержит следующие настройки:

  • Init On Awake – Оставьте включенным, чтобы Nav3D выполнил инициализацию в игровом режиме при выполнении события Awake.
  • Dispose On Destroy – Оставьте включенным, чтобы Nav3D почистил все свои выделенные сущности при уничтожении сцены. Если отключите, то сущности Nav3D останутся и продолжат функционирование и на следующей сцене, которая будет загружена.
  • Min Bucket Size – Минимальный размер ячеек навигационного графа. Должен быть положительным ненулевым числом. Тут поясним чуть подробнее. По сути этот параметр позволяет настраивать уровень детализации навигационного графа. Чем меньше значение параметра - тем выше детализация графа.

Все игровые агенты, которые будут искать путь при помощи Nav3D имеют свой размер, определяемый радиусом, который вы им задаете при создании. (Об этом будет рассказано чуть позже). Минимальный размер ячейки должен быть равен максимальному из радиусов агентов, это будет гарантировать, что агент сможет пройти по любому пути на графе. Если на сцене будут находиться агенты, радиус которых превосходит минимальный размер ячейки графа поиска, то возможны ситуации, когда агенты будут задевать препятствия на сцене. В будущих версиях Nav3D будет реализован поиск пути с учетом размера агента.

*If the Init On Awake and Dispose On Destroy options are disabled, it will be your responsibility to initialize and dispose Nav3D resources. For initialization you will need to call the Nav3DInitializer.Init() method, for disposal – Nav3DInitializer.Utilize(). The value of the Min Bucket Size parameter can also be set via code; to do this, use the MinBucketSize property.

4.2 Nav3DManager

Nav3DManager - вспомогательный static класс. Может быть полезен для проверки факта инициализации Nav3D и/или выполнения определенных действий в момент инициализации.

В нем реализованы следующие члены :

  • Свойство bool Inited, которое показывает, был ли Nav3D уже проинициализирован.
  • Событие event Action OnNav3DInit. Оно срабатывает сразу после инициализации Nav3D. Подписавшись на него вы сможете выполнить какие-либо действия с Nav3D сразу после инициализации. При подписке на ивент ваш делегат сработает моментально, в случае если инициализация уже была произведена ранее.
  • Method IsPointInsideOccupiedVolume(Vector3 _Point)Может быть полезен для определения находится ли точка в ячейке пространства, занятого каким-либо препятствием.

If you try to use public methods from Nav3D.API namespace before Nav3D is initialized, a Nav3DManagerNotInitializedException will be thrown. Any actions with Nav3D entities may be performed only after its initialization.

5. Nav3DObstacle

Nav3D позволяет использовать в качестве препятствий игровые объекты на сцене с компонентом MeshFilter с назначенным Mesh, либо с компонентом Terrain.

*Для препятствий, использующих MeshFilter, убедитесь, что для mesh настройках импорта включена опция “Read/Write Enabled”.

Добавьте компонент Nav3DObstacle к игровому объекту, который вы хотите сделать препятствием на сцене.

Вы увидите его инспектор:

В нем есть следующие настройки:

  • Выбор режима обработки препятствия (обработка препятствия должна выполняться после инициализации Nav3D, чтобы оно учитывалось при поиске пути и, агенты могли его обойти во время движения):
    • Runtime - препятствие будет обработано прямо во время игрового режима после инициализации Nav3D. Это может быть полезно, если препятствие генерируется во время игрового режима.
    • Load from binary - препятствие будет загружено из заранее заготовленного бинарного файла. В большинстве случаев обстановка игровой сцены известна заранее, еще до загрузки сцены и инициализации Nav3D. В таких случаях всегда имеет смысл запекать препятствия сцены в режиме редактора, а на старте сцены загружать их из бинарного файла. Загрузка из бинарного файла всегда гораздо быстрее, чем обработка препятствия непосредственно в игровом режиме (runtime).
  • Process children если включено, то для всех детей transform дерева будет совершен сбор информации о компонентах MeshFilter и Terrain. И все дети, имеющие данные компоненты, будут учтены при обработке препятствия.

* Если вы хотите, чтобы какой-либо дочерний элемент препятствия, содержащий MeshFilter либо Terrain, не учитывался при построении навигационного графа, то навесьте на него компонент Nav3DObstacleIgnoreTag .

  • Auto-update on change - если включено, то в случае изменения положения, поворота или масштаба transform компонента препятствия, будет выполняться его повторная обработка чтобы актуализировать граф поиска. (Препятствие будет сначала удалено из хранилища препятствий, затем будет повторно обработано и добавлено в него).Данная функция доступна для использования только для препятствий с выбранным Runtime режимом обработки.

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

  • Update min period(s) - как часто должно обновляться препятствие (в секундах) при включенном параметре “Update automatically on transform change”.

Для runtime-препятствий возможно их удаление/повторное добавление в хранилище прямо во время игры. Добавление происходит при срабатывании OnEnable(), удаление происходит при срабатывании OnDisable(). Соответственно, любое runtime-препятствие, созданное на сцене во время игры будет обработано и добавлено в хранилище. Если вы удалите или отключите игровой объект препятствия, то оно удалится из хранилища. Повторное включение препятствия вновь добавить его в хранилище.

5.1 Nav3DObstacleLoader

Для использования возможности предзапекания препятствий на сцене в режиме редактора и последующей их загрузки из бинарного файла используется компонент Nav3DObstacleLoader. Вы можете создать его на сцене, используя следующую кнопку верхнего меню:

 

На сцене появится следующий игровой объект:

 

Для всех препятствий на сцене, которые вы хотите запечь, выберите режим обработки Load from binary

 

Далее в инспекторе компонента Nav3DObstacleLoader вы сможете увидеть список всех игровых объектов с компонентом Nav3DObstacle, подлежащих запеканию.

 

Нажмите кнопку “Bake and serialize obstacles” и выберите папку в проекте для сохранения бинарного файла с запеченными данными о препятствиях на сцене.

После успешного запекания инспектор компонента Nav3DObstacleLoader примет такой вид:

 

Инспектор успешно сериализованных Nav3DObstacle будет иметь такой вид:

Теперь в игровом режиме при инициализации Nav3D навигационные графы всех запеченных препятствиях на сцене будут загружены из бинарного файла.

Есть важная особенность касающееся игровых объектов для которых включен статический батчинг. При загрузке навигационного графа из бинарного файла, Nav3DObstacleLoader пытается проверить соответствие данных в бинарном файле и текущих параметров препятствия на сцене (структура иерархии transform, поля transform компонентов, наличие валидного меша в MeshFilter, и прочее). Данная проверка нужна чтобы выкинуть исключение и тем самым уведомить пользователя, что запеченный навигационный файл стал неактуальным, поскольку препятствие было изменено после сохранения бинарного файла. В случае включенного статического батчинга для группы препятствий, валидация никогда не будет успешной, поскольку нельзя получить доступ к мешу препятствия. Так что мы добавили возможность отключения валидации. Для этого в инспекторе Nav3DObstacleLoader снимите галочку “Validate serialized data”.

5.2 Deeper dive into obstacles

  • Как уже было описано выше, для того чтобы препятствие было учтено при поиске пути, необходимо навесить на его игровой объект компонент Nav3DObstacle .
  • В Nav3D существует хранилище препятствий, которое используется при поиске пути. В нем хранятся навигационные графы препятствий на сцене.
  • Все операции с препятствиями (добавление или удаление) ставятся в очередь исполнения и производятся последовательно в отдельном потоке.
  • Под обработкой препятствия подразумевается построение графа проходимости (он же навигационный граф) для каждого препятствия, либо для группы препятствий, а затем добавление этого графа в хранилище препятствий.

Графы проходимости используются при поиске пути на сцене.

Итогом обработки одного препятствия, либо группы препятствий может быть один или несколько графов проходимости, не пересекающихся между собой в пространстве.

5.2.1 Operations with obstacles

Вне зависимости от режима обработки препятствий процедура обработки состоит из нескольких этапов:

  1. Сбор информации о геометрии препятствия для каждого Nav3DObstacle.

    На данном этапе происходит получение списка всех геометрий, образующих препятствие, затем происходит их объединение (кластеризация).

    Положим, в transform иерархии препятствия есть несколько дочерних элементов, у каждого из которых есть MeshFilter с назначенным Mesh. Соответственно, в таком случае будет получено несколько списков треугольников, из которых состоят меши. Далее для каждого списка треугольников будет определен охватывающий объем в виде Bounds. Те списки, чьи Bounds пересекаются, будут объединены. Будем называть каждый такой отдельный список “объемом препятствия”. В результате получается один или несколько объемов препятствий. Это будет проделано для каждого обрабатываемого Nav3DObstacle на сцене.

  2. Кластеризация с уже обработанными препятствиями.

    Проверяется, пересекает(-ют) ли объемы добавляемого препятствия с объемами уже находящихся в хранилище препятствий. Если да, то происходит кластеризация с уже добавленными препятствиями. В результате получается новый список объемов препятствий.

  3. Удаление из хранилища неактуальных объемов хранимых препятствий

    Не актуальными считаются те объемы, которые пересеклись с объемами вновь добавляемого препятствия, и которые вошли с состав новых (кластеризованных) объемов.

  4. Далее происходит построение графов проходимости для новых объемов, затем эти объемы (вместе с графом внутри) добавляются в хранилище препятствий. navigation graphs are constructed for new volumes.

    These volumes are then added to the obstacle storage.

Удаление препятствия из хранилища состоит из следующих этапов:

  1. Из хранилища получается список всех объемов, содержащих треугольники удаляемого препятствия (в каждом объеме могут быть треугольники нескольких препятствий).
  2. Для каждого объема из полученного списка происходит удаление треугольников удаляемого препятствия.
  3. Далее рассматриваются только объемы, в которых после изъятия еще остались треугольники. Для этих объемов пересчитываются ограничивающие Bounds.
  4. Все объемы из первоначального списка удаляются из хранилища препятствий.
  5. Все оставленные объемы с пересчитанными Bounds кластеризуются и вновь добавляются в хранилище препятствий.

5.2.2 Obstacle combinations

Будем называть препятствия с выбранным режимом обработки “Runtime” как runtime-препятствия, а с режимом “Load from binary” - static-препятствия.

Если вы создаете runtime-препятствие во время игрового режима, то оно будет обработано и добавлено в хранилище (при срабатывании OnEnable()). Если вы отключите на сцене уже добавленное runtime-препятствие, то оно будет удалено из хранилища (при срабатывании OnDisable()).

Static-препятствия подразумеваются статичными в том смысле, что они не могут быть добавлены или удалены в игровом режиме. Они будут присутствовать на сцене с того момента, как были загружены из файла и до тех пор, пока Nav3D не будет деинициализирован.

Поскольку вышеописанные операции добавления и удаления для конкретного препятствия могут затрагивать объемы других препятствий на сцене, то получается конфликт между static и runtime препятствиями в случае, если их объемы пересекаются в пространстве.

Так что мы решили ввести несколько ограничений:

  • В момент инициализации сначала происходит загрузка и добавление всех статичных препятствий, затем обработка и добавление runtime-препятствий (если таковые имеются на сцене).
  • При обработке и добавлении runtime-препятствия его объем не должен пересекать объемы static препятствий, в противном случае будет выброшено исключение IntersectStaticObstacleException.
  • Как уже было сказано выше, добавление нескольких runtime-препятствий может привести к тому, что для них будет образован объединенный объем, больший чем каждый из их объемов в отдельности. Ваша задача позаботиться о том, чтобы возможный объединенный объем не пересекал объемы static-препятствий. Для проверки такого потенциального столкновения есть метод Nav3DManager.BoundsCrossStaticObstacles(Bounds _Bounds).

Для избегания таких ситуаций предлагаем вам вообще отказаться от совместного использования static и runtime препятствий на одной сцене.

Если вы все-таки решили использовать оба вида, то рекомендуем создавать runtime-препятствия вдалеке от static препятствий, чтобы минимизировать вероятность пересечения объемов.

6. Nav3DManager

Nav3DManager - вспомогательный static класс. Может быть полезен для проверки факта инициализации Nav3D и/или выполнения определенных действий в момент инициализации.

В нем реализованы следующие члены :

  • Свойство bool Inited, которое показывает, был ли Nav3D уже проинициализирован.
  • Событие event Action OnNav3DInit. Оно срабатывает сразу после инициализации Nav3D. Подписавшись на него вы сможете выполнить какие-либо действия с Nav3D сразу после инициализации. При подписке на ивент ваш делегат сработает моментально, в случае если инициализация уже была произведена ранее.
  • Method IsPointInsideOccupiedVolume(Vector3 _Point)Может быть полезен для определения находится ли точка в ячейке пространства, занятого каким-либо препятствием.

If you try to use public methods from Nav3D.API namespace before Nav3D is initialized, a Nav3DManagerNotInitializedException will be thrown. Any actions with Nav3D entities may be performed only after its initialization.

7. Obstacle combinations

Будем называть препятствия с выбранным режимом обработки “Runtime” как runtime-препятствия, а с режимом “Load from binary” - static-препятствия.

Если вы создаете runtime-препятствие во время игрового режима, то оно будет обработано и добавлено в хранилище (при срабатывании OnEnable()). Если вы отключите на сцене уже добавленное runtime-препятствие, то оно будет удалено из хранилища (при срабатывании OnDisable()).

Static-препятствия подразумеваются статичными в том смысле, что они не могут быть добавлены или удалены в игровом режиме. Они будут присутствовать на сцене с того момента, как были загружены из файла и до тех пор, пока Nav3D не будет деинициализирован.

Поскольку вышеописанные операции добавления и удаления для конкретного препятствия могут затрагивать объемы других препятствий на сцене, то получается конфликт между static и runtime препятствиями в случае, если их объемы пересекаются в пространстве.

Так что мы решили ввести несколько ограничений:

  • В момент инициализации сначала происходит загрузка и добавление всех статичных препятствий, затем обработка и добавление runtime-препятствий (если таковые имеются на сцене).
  • При обработке и добавлении runtime-препятствия его объем не должен пересекать объемы static препятствий, в противном случае будет выброшено исключение IntersectStaticObstacleException.
  • Как уже было сказано выше, добавление нескольких runtime-препятствий может привести к тому, что для них будет образован объединенный объем, больший чем каждый из их объемов в отдельности. Ваша задача позаботиться о том, чтобы возможный объединенный объем не пересекал объемы static-препятствий. Для проверки такого потенциального столкновения есть метод Nav3DManager.BoundsCrossStaticObstacles(Bounds _Bounds).

Для избегания таких ситуаций предлагаем вам вообще отказаться от совместного использования static и runtime препятствий на одной сцене.

Если вы все-таки решили использовать оба вида, то рекомендуем создавать runtime-препятствия вдалеке от static препятствий, чтобы минимизировать вероятность пересечения объемов.

8. Nav3DParticularResolutionRegion

Существует возможность определять области пространства, в которых может быть задан особый минимальный размер ячеек графа поиска

Представим ситуацию, при которой подходящим минимальным размером ячейки графа поиска (разрешением) будет значение 1. При этом есть несколько тесных областей на вашей игровой сцене, где разрешение 1 не дает достаточной детализации графа проходимости. В такой ситуации можно конечно уменьшить минимальный размер ячеек графа поиска для всего пространства вашей сцены, но это повлечет увеличение времени обработки препятствий, а также увеличение среднего времени поиска пути на сцене.

Лучшим выходом в такой ситуации будет уменьшить размер ячеек графа поиска лишь в той области, где хочется увеличить детализацию графа поиска.

Для этого мы реализовали объект Nav3DParticularResolutionRegion, который позволяет задавать регион в пространстве, в котором при построении будет использован специфический минимальный размер ячеек графа поиска.

8.1 Nav3DParticularResolutionRegion: Usage

Для создания области с особым размером минимальных ячеек графа поиска используйте следующую кнопку верхнего меню:

Задайте появившемуся игровому объекту нужное положение на сцене. Далее в инспекторе компонента Nav3DParticularResolutionRegion настройте размеры области, а также укажите нужный минимальный размер ячеек графа поиска . Для визуализации региона включите отображение Gizmos в окне сцены.

Ниже изображен граф поиска для двух одинаковых препятствий, одно из которых находится в регионе с минимальным размером ячеек графа = 0.2. Второе находится вне региона и минимальный размер ячеек графа поиска на всей сцене задан как = 0.4.

Препятствие справа очевидно имеет более детализированный граф поиска, поскольку находится в регионе с меньшим минимальным размером ячеек.

8.2 Nav3DParticularResolutionRegion: Some points

  • Использование регионов разрешения подразумевается для решения задач связанных с проходимостью графа в тесных областях пространства, таких как например узкие тоннели, маленькие отверстия, сквозь которые должна быть обеспечена возможность поиска пути. Но также в таких регионах можно задавать размер минимальной ячейки графа поиска больший, чем размер установленный на всей сцене. Это может быть полезно, когда вы наоборот хотите избежать избыточной детализации графа поиска для некоторых препятствий. Избегание избыточно высокого разрешения графа поиска благоприятно скажется на общей производительности при поиске пути.
  • Октодерево является иерархической структурой, в которой размеры всех ячеек всегда кратны размеру друг друга и от уровня к уровню размер меняется с множителем два (каждый следующий уровень содержит ячейки в два раза меньше чем в предыдущем). Так что вы можете указать лишь желаемый минимальный размер ячейки. На деле реальный минимальный размер ячейки будет вычислен относительно размера указанного при инициализации Nav3D. Если например при инициализации минимальный размер был указан как 0.4, а вы указываете желаемый минимальный размер как 0.3, то фактически будет выбран размер 0.2, поскольку он должен быть уровнем ниже и получен из 0.4 делением на 2. Если же вы выберете желаемый размер как 0.7, то фактический размер будет равен 0.8, поскольку он должен быть уровнем выше и получен умножением на 2.
  • В случае если препятствие находится внутри пересечения нескольких регионов с разным минимальным размером ячеек, при обработке в качестве минимальной ячейки будет выбрано наименьшее значение из значений регионов.
  • Рекомендуем использовать регионы в качестве статических объектов, находящихся на сцене в момент обработки всех препятствий. Операция добавления/удаления региона во время игры повлечет повторную обработку тех runtime-препятствий, которые пересекаются регионом. Static-препятствия никак не отреагируют на удаление/добавление региона. Инициализация и деинициализация региона происходит по событиям OnEnable() и соответственно DoDisable() в Nav3DParticularResolutionRegion. Так что для инициализации региона можно создать его префаб на сцене, для деинициализации - сделать неактивным его GameObject, либо уничтожить его.

9. Nav3DObstacleLoader

Для использования возможности предзапекания препятствий на сцене в режиме редактора и последующей их загрузки из бинарного файла используется компонент Nav3DObstacleLoader. Вы можете создать его на сцене, используя следующую кнопку верхнего меню:

 

На сцене появится следующий игровой объект:

 

Для всех препятствий на сцене, которые вы хотите запечь, выберите режим обработки Load from binary

 

Далее в инспекторе компонента Nav3DObstacleLoader вы сможете увидеть список всех игровых объектов с компонентом Nav3DObstacle, подлежащих запеканию.

 

Нажмите кнопку “Bake and serialize obstacles” и выберите папку в проекте для сохранения бинарного файла с запеченными данными о препятствиях на сцене.

После успешного запекания инспектор компонента Nav3DObstacleLoader примет такой вид:

 

Инспектор успешно сериализованных Nav3DObstacle будет иметь такой вид:

Теперь в игровом режиме при инициализации Nav3D навигационные графы всех запеченных препятствиях на сцене будут загружены из бинарного файла.

Есть важная особенность касающееся игровых объектов для которых включен статический батчинг. При загрузке навигационного графа из бинарного файла, Nav3DObstacleLoader пытается проверить соответствие данных в бинарном файле и текущих параметров препятствия на сцене (структура иерархии transform, поля transform компонентов, наличие валидного меша в MeshFilter, и прочее). Данная проверка нужна чтобы выкинуть исключение и тем самым уведомить пользователя, что запеченный навигационный файл стал неактуальным, поскольку препятствие было изменено после сохранения бинарного файла. В случае включенного статического батчинга для группы препятствий, валидация никогда не будет успешной, поскольку нельзя получить доступ к мешу препятствия. Так что мы добавили возможность отключения валидации. Для этого в инспекторе Nav3DObstacleLoader снимите галочку “Validate serialized data”.

10. Creating and configuring a config via code

Все параметры Nav3DAgentConfig также могут быть заданы из кода.

Для этого вам надо создать экземпляр Nav3DAgentConfig задать нужные значения параметров, затем применить экземпляр к агенту.

  • Предлагается использовать свойство Nav3DAgentConfig.DefaultConfig для создания нового экземпляра.
  • Для получения копии экземпляра предназначен метод Copy() .
  • Для применения конфига к агенту есть метод Nav3DAgent.SetConfig(Nav3DAgentConfig _Config) .

Ниже приведен пример создания экземпляра Nav3DAgentConfig и его применения к агенту.

				
					void ConfigureAgentConfig()
{
   Nav3DAgent myAgent = GetComponent<Nav3DAgent>();

   //create Nav3DAgentConfig instance with default parameters
   Nav3DAgentConfig myConfig = Nav3DAgentConfig.DefaultConfig;

   //set the parameters you want
   myConfig.Radius = 1.2f;
   myConfig.MotionNavigationType = MotionNavigationType.LOCAL;

   //apply config to agent
   myAgent.SetConfig(myConfig.Copy());
}

				
			

11. Nav3DPath

Класс Path предназначен для работы с путями в пространстве.

В общем случае объекты данного типа используются агентами (Nav3DAgent) при выполнении поиска пути. Но вы также можете использовать его отдельно для своих нужд

Разумеется, работа с объектами Nav3DPath возможна только после инициализации Nav3D. Подробнее читайте в разделе"Nav3DInitializer".

11.1 Nav3DPathfindingManager

Данный класс содержит инструменты для работы с поиском путей на сцене. few properties to manage pathfinding tasks limitations..

Для достижения необходимого уровня производительности при использовании Nav3D могут быть полезны следующие свойства:

  • public static int CurrentPathfindingTasksCount – показывает сколько параллельных задач поиска пути активны на данный момент;
  • public static int MaxPathfindingTasks – allows you to limit a number of pathfinding tasks running simultaneously. By default, this property is set to Environment.ProcessorCount - 1

11.2 Nav3DPath: Pathfinding

Для поиска пути необходимо: 

  1. Создать экземпляр Nav3DPath используя конструктор: new Nav3DPath().
  2. Для созданного объекта Nav3DPath вызовите один из методов:

Для поиска пути между двумя точками:

				
					public void Find(
Vector3 _Start,
Vector3 _End,
Action _OnSuccess = null,
Action<PathfindingError> _OnFail = null
)
				
			

Назначение параметров:

  • Action _OnSuccess - колбэк успешного завершения поиска пути.
  • Action<PathfindingError> _OnFail - колбек завершения поиска пути в случае ошибки, содержит данные об ошибке.

Для поиска пути между множеством точек (больше 2):

				
					public void Find(
       Vector3[] _Targets,
       bool _Loop,
       bool _SkipUnpassableTargets = false,
       Action _OnSuccess = null,
       Action<PathfindingError> _OnFail = null
   )

				
			

Назначение параметров:

  • bool _Loop - нужно ли замкнуть путь (будет найден путь между первой и последней точкой в наборе).
  • bool _SkipUnpassableTargets = false - будет ли пропускаться каждая точка, до которой поиск пути завершился с ошибкой. Если параметр установлен в false, то при неудаче поиска пути между любой парой точек, будет выполнен _OnFail колбэк, и поиск будет прекращен.

Имеется возможность повторить последний поиск пути. Это может быть полезно, если вы считаете, что последний найденный путь больше не актуален, например в случае, если изменилась конфигурация сцены (какие-либо препятствия были добавлены или удалены).

Для этого вызовите метод public void Update() .

11.3 Nav3DPath: Properties

  • public bool IsValid { get; } - показывает, был ли успешным последний завершенный поиск пути. Свойство примет значение false, если изменить значение одного из свойств Smooth or SmoothRatio .
  • public bool IsPathfindingInProgress { get; } - выполняется ли поиск пути в данный момент.
  • public Vector3[] Trajectory { get; } - траектория последнего найденного пути. IsValid Используйте свойство IsValid для проверки того, что значение достоверно.
  • public Bounds Bounds { get; } - объем пространства, который занят найденным путем.
  • public bool Smooth { get; set; } - нужно ли производить сглаживание пути.
  • public int SmoothRatio { get; set; } - количество проходов сглаживания по отношению к минимальному размеру ячейки графа поиска, по умолчанию установлено как 3. Не рекомендуется увеличивать это значение без необходимости, так как это увеличит время поиска пути, в случае если сглаживание включено (свойство Smooth == true).
  • public int Timeout { get; set; } - максимальное время поиска пути. В случае, если поиск пути длится дольше, произойдет выполнение колбека Action<PathfindingError> _OnFail , если он был передан в Find().
  • public bool TryRepositionStartIfOccupied { get; set; } - в случае, если для поиска пути указана стартовая точка, находящаяся в ячейке пространства, занятой препятствием, пытаться найти соседнюю свободную ячейку и осуществлять поиск из нее.
  • public bool TryRepositionTargetIfOccupied  { get; set; } - в случае, если для поиска пути указана целевая точка, находящаяся в ячейке пространства, занятой препятствием, пытаться найти соседнюю свободную ячейку и осуществлять поиск до нее.
  • public PathfindingResult { get; } - результат последнего успешного поиска пути.

11.4 Nav3DPath: Events

Для удобства отслеживания окончания поиска пути реализованы события:

  • public event Action OnPathfindingSuccess - срабатывает при успешном завершении поиска пути.
  • public event Action<PathfindingError> OnPathfindingFail - срабатывает при возникновении ошибки при поиске пути.
  • public event Action OnPathfindingComplete - срабатывает как при успешном, так и при неуспешном завершении поиска пути.

11.5 Nav3DPath: Dispose

После того как вы завершили работу с объектом Nav3DPath, необходимо вызвать метод public void Dispose(). необходимо вызвать метод public void Dispose(). Это необходимо для удаления пути из хранилища препятствий. В противном случае при добавлении/обновлении/удалении какого-либо препятствия, путь будет проверяться на необходимость обновления, что будет занимать вычислительные ресурсы. Любые пути, инициализированные на сцене, для которых не был вызван Nav3DPath , будут занимать вычислительные ресурсы.

11.6 PathfindingError

Содержит сведения об ошибке в случае срабатывания _OnFail колбэка.

Свойства:

  • public PathfindingResultCode Reason причина неудачи поиска пути
    Возможные значения свойства:
ValueОписание
SUCCEEDEDПоиск пути завершился успешно.
PATH_DOES_NOT_EXISTМежду точками не существует пути. Это возможно если хотя бы одна из точек окружена препятствиями со всех сторон.
TIMEOUTПоиск пути занял больше времени чем разрешено и был прерван.
CANCELEDПоиск пути был завершен по указанию пользователя, или по внутренней логике Nav3D.
START_POINT_INSIDE_OBSTACLEПоиск пути не удался, потому что начальная точка пути находится внутри препятствия
TARGET_POINT_INSIDE_OBSTACLEPathfinding has been canceled because the target point of the path is inside an obstacle.
UNKNOWNВнутренняя ошибка.
  • public string Msg сообщение с более подробной информацией об ошибке.

11.7 PathfindingResult

Хранит результаты поиска пути и временные затраты.

Временные затраты поиска пути:

    • public TimeSpan PathfindingDuration { get; } - длительность выполнения поиска пути (A*).
    • public TimeSpan OptimizingDuration  { get; } - длительность выполнения оптимизации пути.
    • public TimeSpan SmoothingDuration   { get; } - длительность выполнения сглаживания пути.

Результаты поиска пути:

    • public Vector3[] RawPath { get; } - найденный путь после работы алгоритма A*
    • public Vector3[] PathOptimized { get; } - путь после применения алгоритма оптимизации.
    • public Vector3[] PathSmoothed  { get; } - путь после применения алгоритма сглаживания к оптимизированному пути. Если Smooth = false, то содержимое будет идентично PathOptimized.
    • public int[] TargetIndices { get; } – the indices of the target points in the PathSmoothed array. The target points mean the points used when calling Nav3DPath.Find().
    • public PathfindingResultCode Result { get; } - код результата поиска.

11.8 Usage example

Ниже приведен пример использования Nav3DPath.

				
					using Nav3D.API;
using System;
using System.Linq;
using UnityEngine;

class YourGameScenario : MonoBehaviour
{
   #region Attributes

   Vector3[] m_FoundPath;

   #endregion
  
   #region Unity events

   void Start()
   {
       Nav3DManager.OnNav3DInit += () =>
       {
           Vector3 a = new Vector3(-10, -10, -10);
           Vector3 b = new Vector3(10, 10, 10);

           FindPath(a, b, PrintPath);
       };
   }

   void OnDrawGizmos()
   {
       if (!Application.isPlaying || !enabled)
           return;

       if (m_FoundPath != null && m_FoundPath.Any())
       {
           for (int i = 0; i < m_FoundPath.Length - 1; i++)
               Gizmos.DrawLine(m_FoundPath[i], m_FoundPath[i + 1]);
       }
   }
  
   #endregion

   #region Service methods

   //your method for pathfinding from A to B
   void FindPath(Vector3 _A, Vector3 _B, Action<Vector3[]> _OnPathFound)
   {
       //create Nav3DPathPath instance
       Nav3DPath path = new Nav3DPath(gameObject.name);

       //perform pathfinding from _A to _B
       path.Find(
               _A,
               _B,
               _OnSuccess: () =>
               {
                   //notify that path was found
                   Debug.Log("Path successfully found!");

                   //invoke callback
                   _OnPathFound(path.Trajectory);

                   //finish work with Nav3DPath instance
                   path.Dispose();
               }
           );
   }

   void PrintPath(Vector3[] _Path)
   {
       m_FoundPath = _Path;

       Debug.Log($"Path points: {string.Join(", ", m_FoundPath)}");
   }

   #endregion
}

				
			

11.9 Nav3DPathTester

Мы реализовали специальный компонент (Nav3DPathTester), который может быть использован при построении игровых сцен для проверки того, как будет проходить путь в разных местах сцены.

  • Для его использования вам надо добавить на любой игровой объект на сцене компонент Nav3DPathTester.
  • Для его работы система Nav3D должна быть инициализирована, так что его применение возможно только в игровом режиме.

После добавления компонента вы увидите его инспектор:

Здесь смысл всех параметров соответствует смыслу параметров метода Nav3DPath.Find() .

Добавьте на игровую сцену несколько игровых объектов, которые будут служить в качестве точек между которыми будет искаться путь. Далее добавьте эти объекты в список Targets в инспекторе Nav3DPathTester.

В игровом режиме, при включенном Gizmos вы сможете увидеть как путь пройдет через все объекты Targets.

Ниже показаны два примера тестового пути для трех объектов при выключенной и включенной опцией Loop.

12. Deeper dive into obstacles

  • Как уже было описано выше, для того чтобы препятствие было учтено при поиске пути, необходимо навесить на его игровой объект компонент Nav3DObstacle .
  • В Nav3D существует хранилище препятствий, которое используется при поиске пути. В нем хранятся навигационные графы препятствий на сцене.
  • Все операции с препятствиями (добавление или удаление) ставятся в очередь исполнения и производятся последовательно в отдельном потоке.
  • Под обработкой препятствия подразумевается построение графа проходимости (он же навигационный граф) для каждого препятствия, либо для группы препятствий, а затем добавление этого графа в хранилище препятствий.

Графы проходимости используются при поиске пути на сцене.

Итогом обработки одного препятствия, либо группы препятствий может быть один или несколько графов проходимости, не пересекающихся между собой в пространстве.

12.1 Operations with obstacles

Вне зависимости от режима обработки препятствий процедура обработки состоит из нескольких этапов:

  1. Сбор информации о геометрии препятствия для каждого Nav3DObstacle.

    На данном этапе происходит получение списка всех геометрий, образующих препятствие, затем происходит их объединение (кластеризация).

    Положим, в transform иерархии препятствия есть несколько дочерних элементов, у каждого из которых есть MeshFilter с назначенным Mesh. Соответственно, в таком случае будет получено несколько списков треугольников, из которых состоят меши. Далее для каждого списка треугольников будет определен охватывающий объем в виде Bounds. Те списки, чьи Bounds пересекаются, будут объединены. Будем называть каждый такой отдельный список “объемом препятствия”. В результате получается один или несколько объемов препятствий. Это будет проделано для каждого обрабатываемого Nav3DObstacle на сцене.

  2. Кластеризация с уже обработанными препятствиями.

    Проверяется, пересекает(-ют) ли объемы добавляемого препятствия с объемами уже находящихся в хранилище препятствий. Если да, то происходит кластеризация с уже добавленными препятствиями. В результате получается новый список объемов препятствий.

  3. Удаление из хранилища неактуальных объемов хранимых препятствий

    Не актуальными считаются те объемы, которые пересеклись с объемами вновь добавляемого препятствия, и которые вошли с состав новых (кластеризованных) объемов.

  4. Далее происходит построение графов проходимости для новых объемов, затем эти объемы (вместе с графом внутри) добавляются в хранилище препятствий. navigation graphs are constructed for new volumes.

    These volumes are then added to the obstacle storage.

Удаление препятствия из хранилища состоит из следующих этапов:

  1. Из хранилища получается список всех объемов, содержащих треугольники удаляемого препятствия (в каждом объеме могут быть треугольники нескольких препятствий).
  2. Для каждого объема из полученного списка происходит удаление треугольников удаляемого препятствия.
  3. Далее рассматриваются только объемы, в которых после изъятия еще остались треугольники. Для этих объемов пересчитываются ограничивающие Bounds.
  4. Все объемы из первоначального списка удаляются из хранилища препятствий.
  5. Все оставленные объемы с пересчитанными Bounds кластеризуются и вновь добавляются в хранилище препятствий.

12.2 Obstacle combinations

Будем называть препятствия с выбранным режимом обработки “Runtime” как runtime-препятствия, а с режимом “Load from binary” - static-препятствия.

Если вы создаете runtime-препятствие во время игрового режима, то оно будет обработано и добавлено в хранилище (при срабатывании OnEnable()). Если вы отключите на сцене уже добавленное runtime-препятствие, то оно будет удалено из хранилища (при срабатывании OnDisable()).

Static-препятствия подразумеваются статичными в том смысле, что они не могут быть добавлены или удалены в игровом режиме. Они будут присутствовать на сцене с того момента, как были загружены из файла и до тех пор, пока Nav3D не будет деинициализирован.

Поскольку вышеописанные операции добавления и удаления для конкретного препятствия могут затрагивать объемы других препятствий на сцене, то получается конфликт между static и runtime препятствиями в случае, если их объемы пересекаются в пространстве.

Так что мы решили ввести несколько ограничений:

  • В момент инициализации сначала происходит загрузка и добавление всех статичных препятствий, затем обработка и добавление runtime-препятствий (если таковые имеются на сцене).
  • При обработке и добавлении runtime-препятствия его объем не должен пересекать объемы static препятствий, в противном случае будет выброшено исключение IntersectStaticObstacleException.
  • Как уже было сказано выше, добавление нескольких runtime-препятствий может привести к тому, что для них будет образован объединенный объем, больший чем каждый из их объемов в отдельности. Ваша задача позаботиться о том, чтобы возможный объединенный объем не пересекал объемы static-препятствий. Для проверки такого потенциального столкновения есть метод Nav3DManager.BoundsCrossStaticObstacles(Bounds _Bounds).

Для избегания таких ситуаций предлагаем вам вообще отказаться от совместного использования static и runtime препятствий на одной сцене.

Если вы все-таки решили использовать оба вида, то рекомендуем создавать runtime-препятствия вдалеке от static препятствий, чтобы минимизировать вероятность пересечения объемов.

13. Nav3DAgent

У Nav3DAgent это основной класс, осуществляющий движение игровых юнитов в пространстве игровой сцены.

  1. Nav3DAgent возможно только после инициализации Nav3D. Подробнее читайте в разделе Nav3DInitializer .
  2. Используйте этот класс в качестве компонента для ваших игровых юнитов.
  3. Для использования Nav3DAgent необходимо настроить его поведение. Это возможно сделать с помощью использования класса Nav3DAgentConfig.

13.1 Nav3DAgentManager

В этом классе доступны методы получения списка агентов на сцене, находящихся в некоторой области:

  • public static Nav3DAgent[] GetAgentsInBounds(Bounds _Bounds) - получить список агентов Nav3DAgent, находящихся в Bounds.
  • public static Nav3DAgent[] GetAgentsInSphere(Vector3 _Center, float _Radius) - получить список агентов Nav3DAgent, находящихся в сфере с центром в _Center, радиусом _Radius.

13.2 Nav3DAgentConfig

Nav3DAgentConfig служит описанием агента и позволяет настраивать его поведение и все необходимые параметры.

Вы можете создать экземпляр через контекстное меню вкладки Проект.

После создания описания в инспекторе вы увидите следующий список групп параметров:

Приведем пояснение назначения параметров и их допустимые величины.

Behavior

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Motion Navigation Type
MotionNavigationType
enum MotionNavigationType
COMBINED, GLOBAL, LOCAL

Основное назначение всех агентов - движение к какой-либо точке в пространстве. Агенты могут двигаться с помощью трех способов ориентирования в пространстве.

  • Используя глобальный путь (GLOBAL). В таком случае агент выполнит поиск пути и будет двигаться по нему, невзирая на внешние условия (другие агенты, находящиеся слишком близко края препятствий).
  • С использованием только локального уклонения (LOCAL). Агент не будет использовать поиск пути для движения, а будет двигаться к цели по прямой, попутно уклоняясь от других агентов и препятствий, когда они встречаются на курсе движения. Разумеется не всякое препятствие может быть преодолено таким образом.
  • Наконец, агент может осуществлять движение к цели используя поиск пути и локальное уклонение одновременно (COMBINED). Агент будет двигаться по найденному пути и уклоняться от подошедших близко других агентов, а также находящихся слишком близко препятствий.

Radius

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Radius
Radius
float
>0

Радиус агента используется для осуществления маневров локального уклонения. Установление корректного радиуса важно для эффективного выполнения локального уклонения как самим агентом, так и прочими агентами поблизости. Советуем настраивать радиус так, чтобы все визуальное содержимое игрового юнита, коим является агент, находилось внутри сферы.

Speed

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Speed
Speed
float
>0

Скорость движения агента. Можете менять ее в любой момент времени, если потребуется.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Max Speed
Max Speed
float
>Speed

Максимальная скорость агента. Этот параметр нужен для выполнения локального уклонения. В некоторых ситуациях агенту может потребоваться ускориться, чтобы избежать столкновения. Если значение будет слишком велико, то порой агент может двигаться рывками при выполнении локального уклонения. Так что советуем выставлять максимальную скорость чуть больше чем Speed(больше менее чем в полтора раза).

Для вашего удобства в инспекторе имеется два способа установления этого значения. С помощью конкретного значения. Либо с помощью множителя для Speed. Советуем использовать множитель, для того чтобы максимальная скорость зависела от Speed агента. Тогда MaxSpeed будет меняться вслед за изменением Speed

Local avoidance

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Agents considered number limit
Agents considered number limit
bool
true, false

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

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Agents number
ConsideredAgentsNumberLimit
int
>=1

Количество агентов, которые берутся в рассмотрение из всех ближайших агентов.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Avoid static obstacles
AvoidStaticObstacles
bool
true, false

Нужно ли выполнять локальное уклонение от статических препятствий

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

Не рекомендуется включать эту возможность без надобности, поскольку она оказывает нагрузку на производительность.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
ORCA Tau
ORCATau
float
>0

Временной диапазон вычисления скоростного препятствия. Не рекомендуем менять этот параметр

Лучше понять его смысл вам поможет оригинальная статья по ORCA Reciprocal n-body Collision Avoidance. Jur van den Berg, Stephen J. Guy, Ming Lin, and Dinesh Manocha

Поиск пути

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Pathfinding timeout (ms)
PathfindingTimeout
int
>0

Максимальное время, отведенное на выполнение поиска пути. При превышении этого времени поиск(pathfinding) будет отменен, и будет вызван колбек _OnPathfindingFail.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Smooth the path
SmoothPath
bool
true, false

Нужно ли сглаживать найденный путь.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Samples per min bucket volume
SmoothRatio
int
>0

Количество сегментов пути на один минимальный объем октодерева, получаемых при сглаживании исходного пути. Не следует избыточно увеличивать этот параметр, так как это увеличивает итоговое время поиска пути.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Auto-update path on stagnant behavior
AutoUpdatePath
bool
true, false

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

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

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Auto-update cooldown (ms)
PathAutoUpdateCooldown
int
>=1

Минимальный период автокорректировки пути. Если область пространства будет слишком заполнена другими агентами, то пересчет пути может быть слишком частым, что негативно повлияет на производительность в случае большого количества агентов на сцене. Рекомендуем ограничить частоту автокорректировки несколькими секундами.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Try reposition target if occupied
TryRepositionTargetIfOccupied
bool
true, false

Включение параметра позволит совершить попытку поиска пути до соседней свободной ячейки, если целевая точка оказалась в ячейке, занятой препятствием.

Если параметр выключен, тогда в таком случае поиск пути будет прерван с ошибкой GOAL_POINT_INSIDE_OBSTACLE .

Motion

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Target reach distance
TargetReachDistance
float
>=0

Расстояние достижения цели. Когда вы отдаете агенту приказание достичь какой-либо цели, цель будет считаться достигнутой, когда pivot агента совпадет с координатой цели (расстояние между ними будет равным 0). Это может быть неудобно, если целью является объект с мешем, допустим планета в космосе. В таком случае выставьте этот параметр равным сумме радиуса видимой части агента и радиуса планеты. Тогда агент остановится, достигнув поверхности планеты.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Max rotation in degrees per fixed update tick
MaxAgentDegreesRotationPerTick
float
>=0

Максимальное количество градусов, на которое может повернуться агент при выполнении поворота в сторону движения.
В процессе движения агент поворачивается в сторону вектора скорости. Если вектор скорости круто меняется в процессе движения, то поворачивание агента может выглядеть резким. Чтобы сделать его более плавным, выставите этот параметр не слишком большим.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Rotation vector lerp factor
RotationVectorLerpFactor
float
(0 - 1)

In order to make the rotation of an agent even more smoother, when computing the rotation vector the frame rotation vector and the value of rotation vector for a few last frames are used.

Decreasing the parameter makes the rotation smoother, increasing it makes it sharper.

Velocity blending

При использовании глобального поиска пути и локального уклонения агент двигается, используя три вектора скорости:

  1. Вектор скорости следования по пути.
  2. Вектор скорости уклонения от агентов.
  3. Вектор скорости уклонения от препятствий.

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

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

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

Ниже приведены пояснения для параметров весов. Обратите внимание, что для каждой ситуации используются отдельные параметры

Все веса задаются типом float и должны иметь значение более 0

Соответствующие названия свойств в Nav3DAgentConfig:

  • PathVelocityWeight
  • PathVelocityWeight1
  • PathVelocityWeight2
  • AgentsAvoidanceVelocityWeight
  • AgentsAvoidanceVelocityWeight1
  • AgentsAvoidanceVelocityWeight2
  • ObstacleAvoidanceVelocityWeight
  • ObstacleAvoidanceVelocityWeight1
  • ObstacleAvoidanceVelocityWeight2

Debug

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Use log
UseLog
bool
true, false

Нужно ли логгировать работу агента.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Log records count
LogSize
int
>0

Размер лога.

13.2.1 Creating and configuring a config via code

Все параметры Nav3DAgentConfig также могут быть заданы из кода.

Для этого вам надо создать экземпляр Nav3DAgentConfig задать нужные значения параметров, затем применить экземпляр к агенту.

  • Предлагается использовать свойство Nav3DAgentConfig.DefaultConfig для создания нового экземпляра.
  • Для получения копии экземпляра предназначен метод Copy() .
  • Для применения конфига к агенту есть метод Nav3DAgent.SetConfig(Nav3DAgentConfig _Config) .

Ниже приведен пример создания экземпляра Nav3DAgentConfig и его применения к агенту.

				
					void ConfigureAgentConfig()
{
   Nav3DAgent myAgent = GetComponent<Nav3DAgent>();

   //create Nav3DAgentConfig instance with default parameters
   Nav3DAgentConfig myConfig = Nav3DAgentConfig.DefaultConfig;

   //set the parameters you want
   myConfig.Radius = 1.2f;
   myConfig.MotionNavigationType = MotionNavigationType.LOCAL;

   //apply config to agent
   myAgent.SetConfig(myConfig.Copy());
}

				
			

13.3 Nav3DAgent: Methods

Как упоминалось выше, вы можете использовать скрипт Nav3DAgent в качестве компонента для вашего игрового объекта и обращаться к нему через GetComponent() .

Для управления Nav3DAgent реализованы следующие публичные методы:

  • установка Nav3DAgentConfig.
				
					public void SetConfig(Nav3DAgentConfig _Config)
				
			
  • Команда двигаться к точке.
				
					public void MoveTo(
Vector3                  _Point,
Action                   _OnReach           = null,
Action<PathfindingError> _OnPathfindingFail = null,
float?                   _ReachDistance     = null)
				
			

Параметры:

    • Vector3 _Point - целевая точка.
    • Action _OnReach - колбэк достижения целевой точки.
    • Action<PathfindingError> _OnPathfindingFail - колбэк ошибки поиска пути.
    • float? _ReachDistance - расстояние до целевой точки, необходимое для завершения следования и срабатывания _OnFinished.
  • Команда последовательно двигаться по списку точек. Будет найден путь, проходящий через каждую точку массива.
				
					public void MoveToPoints(
Vector3[]                _Points,
bool                     _Loop                  = false,
bool                     _StartFromClosest      = false,
bool                     _SkipUnpassableTargets = false,
float?                   _ReachDistance         = null,
Action<Vector3>  _OnTargetPointPassed           = null,
Action                   _OnFinished            = null,
Action<PathfindingError> _OnPathfindingFail     = null)

				
			

Параметры:

  • Vector3[] _Points – a target points.
  • bool _Loop - замыкать ли движение по точкам. Если true, агент будет двигаться по последовательности точек бесконечно, переходя к первой каждый раз при достижении последней.
  • bool_StartFromClosest - начинать ли движение с ближайшей точки массива, а не с первой.
  • bool_SkipUnpassableTargets - будет ли пропускаться каждая точка, до которой поиск пути завершился с ошибкой. Если параметр установлен в false, то при неудаче поиска пути между любой парой точек, будет выполнен _OnFail колбэк, и поиск будет прекращен.
  • float? _ReachDistance - расстояние до целевой точки, необходимое для завершения следования и срабатывания _OnFinished.
  • Action<Vector3> _OnTargetPointPassed - колбэк, срабатывающий при прохождении агентом одной из целевых точек пути.
  • Action _OnFinished - колбэк, срабатывающий при прохождении агентом последней точки пути. Колбэк не сработает, если _Loop = true.
  • Action<PathfindingError> _OnPathfindingFail - колбэк ошибки поиска пути.
  • Начать преследование transform цели.

				
					public void FollowTarget(
Transform                _Target,
bool                     _FollowContinuously,
float                    _TargetOffsetUpdate,
float                    _TargetReachDistance   = 0,
Action                   _OnReach               = null,
Action                   _OnFail                = null,
Action<PathfindingError> _OnPathfindingFail     = null)

				
			

Параметры:

    • Transform _Target - цель для преследования.
    • bool _FollowContinuously - преследовать ли цель без окончания. Если true, то агент никогда не прекратит преследование и не вызовет _OnReach. При достижении цели просто будет находиться рядом, пока цель снова не отдалится.
    • float _TargetOffsetUpdate - величина смещения цели, для которой наступит перерасчет пути до цели.
    • float _TargetReachDistance - расстояние до transform цели, необходимое для завершения преследования и срабатывания _OnReach.
    • Action _OnReach - колбэк достижения цели преследования.
    • Action _OnFail - колбэк, срабатывающий в случае если transform цели был уничтожен или переведен в неактивное состояние на сцене.
    • Action<PathfindingError> _OnPathfindingFail - колбэк ошибки поиска пути.
  • Останавливает выполнение текущей действующей команды
				
					public void Stop()
				
			
  • Возвращает агентов, удовлетворяющих предикату, находящихся в заданном радиусе от агента.
				
					public Nav3DAgent[] GetAgentsInRadius(float _Radius, Predicate<Nav3DAgent> _Predicate = null)
				
			

Примеры по использованию Nav3DAgent вы можете найти в демо сценах, расположенных в папке Nav3D/Demo.

13.4 Nav3DAgent: Debug

У Nav3DAgent реализован инспектор, предоставляющий несколько полезных функций, помогающих в отладке и дающих лучшее понимание о взаимодействии объектов на сцене.

13.4.1 Debug drawing

В первой секции вы можете визуализировать агента и его ближайшее окружение. Делать это следует со включенным отображением Gizmos на сцене:

1.Визуализация радиуса агента.

2. Визуализация нормализованных скоростей агента.

Желтый - вектор скорости следования по глобальному пути (вектор направления от положения агента к следующей целевой точке на пути).

Зеленый - вектор скорости локального уклонения.

Синий - результирующий вектор движения (смесь вектора следования по пути и вектора локального уклонения).

3. Визуализация пути, по которому следует агент.

4. Визуализация близлежащих агентов, которые могут быть учтены при выполнении локального уклонения.

При выполнении локального уклонения в зависимости от настройки допустимого количества рассматриваемых агентов (в описании агента) будет взято n ближайших агентов из всех близлежащих агентов.

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

6. Всё сразу

13.4.2 Agent log

Тут вы можете скопировать в буфер обмена содержимое лога агента нажав на кнопку, если логирование включено в описании агента.

13.5 Nav3DEvader

Мы реализовали отдельный контроллер, поведение которого состоит в уклонении от находящихся рядом агентов, и статических препятствий, если вдруг он попал в соприкосновение с ними.

Его поведение выглядит довольно интересно, и продемонстрировано в демо Nav3D/Demo/EvadersCrowd.

В инспекторе компонента имеются следующие настройки:

  • Radius - радиус, для которого проверяется пересечение с другими агентами и прочими сущностями.
  • Max Speed - максимально возможная скорость при выполнении избегания столкновения.
  • Speed Decay Factor - множитель затухания скорости после завершения избегания. Чем больше значение, тем быстрее остановится Nav3DEvader после избегания столкновения. допустимое значение в диапазоне (0 - 1).

13.6 Nav3DSphereShell

Представляет собой сферическую оболочку, которая воспринимается агентами как объект для уклонения. Nav3DSphereShell может приводиться в движение извне, агенты на сцене, а также Nav3DAgents and Nav3DEvader, будут уклоняться от столкновения с ним.

Поведение Nav3DSphereShell продемонстрировано в демо Nav3D/Demo/SphereShellDemo.

В инспекторе компонента вы можете настроить радиус сферы.

14. Debug drawing

В первой секции вы можете визуализировать агента и его ближайшее окружение. Делать это следует со включенным отображением Gizmos на сцене:

1.Визуализация радиуса агента.

2. Визуализация нормализованных скоростей агента.

Желтый - вектор скорости следования по глобальному пути (вектор направления от положения агента к следующей целевой точке на пути).

Зеленый - вектор скорости локального уклонения.

Синий - результирующий вектор движения (смесь вектора следования по пути и вектора локального уклонения).

3. Визуализация пути, по которому следует агент.

4. Визуализация близлежащих агентов, которые могут быть учтены при выполнении локального уклонения.

При выполнении локального уклонения в зависимости от настройки допустимого количества рассматриваемых агентов (в описании агента) будет взято n ближайших агентов из всех близлежащих агентов.

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

6. Всё сразу

15. Nav3DParticularResolutionRegion: Usage

Для создания области с особым размером минимальных ячеек графа поиска используйте следующую кнопку верхнего меню:

Задайте появившемуся игровому объекту нужное положение на сцене. Далее в инспекторе компонента Nav3DParticularResolutionRegion настройте размеры области, а также укажите нужный минимальный размер ячеек графа поиска . Для визуализации региона включите отображение Gizmos в окне сцены.

Ниже изображен граф поиска для двух одинаковых препятствий, одно из которых находится в регионе с минимальным размером ячеек графа = 0.2. Второе находится вне региона и минимальный размер ячеек графа поиска на всей сцене задан как = 0.4.

Препятствие справа очевидно имеет более детализированный граф поиска, поскольку находится в регионе с меньшим минимальным размером ячеек.

16. Nav3DParticularResolutionRegion: Some points

  • Использование регионов разрешения подразумевается для решения задач связанных с проходимостью графа в тесных областях пространства, таких как например узкие тоннели, маленькие отверстия, сквозь которые должна быть обеспечена возможность поиска пути. Но также в таких регионах можно задавать размер минимальной ячейки графа поиска больший, чем размер установленный на всей сцене. Это может быть полезно, когда вы наоборот хотите избежать избыточной детализации графа поиска для некоторых препятствий. Избегание избыточно высокого разрешения графа поиска благоприятно скажется на общей производительности при поиске пути.
  • Октодерево является иерархической структурой, в которой размеры всех ячеек всегда кратны размеру друг друга и от уровня к уровню размер меняется с множителем два (каждый следующий уровень содержит ячейки в два раза меньше чем в предыдущем). Так что вы можете указать лишь желаемый минимальный размер ячейки. На деле реальный минимальный размер ячейки будет вычислен относительно размера указанного при инициализации Nav3D. Если например при инициализации минимальный размер был указан как 0.4, а вы указываете желаемый минимальный размер как 0.3, то фактически будет выбран размер 0.2, поскольку он должен быть уровнем ниже и получен из 0.4 делением на 2. Если же вы выберете желаемый размер как 0.7, то фактический размер будет равен 0.8, поскольку он должен быть уровнем выше и получен умножением на 2.
  • В случае если препятствие находится внутри пересечения нескольких регионов с разным минимальным размером ячеек, при обработке в качестве минимальной ячейки будет выбрано наименьшее значение из значений регионов.
  • Рекомендуем использовать регионы в качестве статических объектов, находящихся на сцене в момент обработки всех препятствий. Операция добавления/удаления региона во время игры повлечет повторную обработку тех runtime-препятствий, которые пересекаются регионом. Static-препятствия никак не отреагируют на удаление/добавление региона. Инициализация и деинициализация региона происходит по событиям OnEnable() и соответственно DoDisable() в Nav3DParticularResolutionRegion. Так что для инициализации региона можно создать его префаб на сцене, для деинициализации - сделать неактивным его GameObject, либо уничтожить его.

17. Agent log

Тут вы можете скопировать в буфер обмена содержимое лога агента нажав на кнопку, если логирование включено в описании агента.

18. Nav3DPathfindingManager

Данный класс содержит инструменты для работы с поиском путей на сцене. few properties to manage pathfinding tasks limitations..

Для достижения необходимого уровня производительности при использовании Nav3D могут быть полезны следующие свойства:

  • public static int CurrentPathfindingTasksCount – показывает сколько параллельных задач поиска пути активны на данный момент;
  • public static int MaxPathfindingTasks – allows you to limit a number of pathfinding tasks running simultaneously. By default, this property is set to Environment.ProcessorCount - 1

19. Nav3DPath: Pathfinding

Для поиска пути необходимо: 

  1. Создать экземпляр Nav3DPath используя конструктор: new Nav3DPath().
  2. Для созданного объекта Nav3DPath вызовите один из методов:

Для поиска пути между двумя точками:

				
					public void Find(
Vector3 _Start,
Vector3 _End,
Action _OnSuccess = null,
Action<PathfindingError> _OnFail = null
)
				
			

Назначение параметров:

  • Action _OnSuccess - колбэк успешного завершения поиска пути.
  • Action<PathfindingError> _OnFail - колбек завершения поиска пути в случае ошибки, содержит данные об ошибке.

Для поиска пути между множеством точек (больше 2):

				
					public void Find(
       Vector3[] _Targets,
       bool _Loop,
       bool _SkipUnpassableTargets = false,
       Action _OnSuccess = null,
       Action<PathfindingError> _OnFail = null
   )

				
			

Назначение параметров:

  • bool _Loop - нужно ли замкнуть путь (будет найден путь между первой и последней точкой в наборе).
  • bool _SkipUnpassableTargets = false - будет ли пропускаться каждая точка, до которой поиск пути завершился с ошибкой. Если параметр установлен в false, то при неудаче поиска пути между любой парой точек, будет выполнен _OnFail колбэк, и поиск будет прекращен.

Имеется возможность повторить последний поиск пути. Это может быть полезно, если вы считаете, что последний найденный путь больше не актуален, например в случае, если изменилась конфигурация сцены (какие-либо препятствия были добавлены или удалены).

Для этого вызовите метод public void Update() .

20. Nav3DPath: Properties

  • public bool IsValid { get; } - показывает, был ли успешным последний завершенный поиск пути. Свойство примет значение false, если изменить значение одного из свойств Smooth or SmoothRatio .
  • public bool IsPathfindingInProgress { get; } - выполняется ли поиск пути в данный момент.
  • public Vector3[] Trajectory { get; } - траектория последнего найденного пути. IsValid Используйте свойство IsValid для проверки того, что значение достоверно.
  • public Bounds Bounds { get; } - объем пространства, который занят найденным путем.
  • public bool Smooth { get; set; } - нужно ли производить сглаживание пути.
  • public int SmoothRatio { get; set; } - количество проходов сглаживания по отношению к минимальному размеру ячейки графа поиска, по умолчанию установлено как 3. Не рекомендуется увеличивать это значение без необходимости, так как это увеличит время поиска пути, в случае если сглаживание включено (свойство Smooth == true).
  • public int Timeout { get; set; } - максимальное время поиска пути. В случае, если поиск пути длится дольше, произойдет выполнение колбека Action<PathfindingError> _OnFail , если он был передан в Find().
  • public bool TryRepositionStartIfOccupied { get; set; } - в случае, если для поиска пути указана стартовая точка, находящаяся в ячейке пространства, занятой препятствием, пытаться найти соседнюю свободную ячейку и осуществлять поиск из нее.
  • public bool TryRepositionTargetIfOccupied  { get; set; } - в случае, если для поиска пути указана целевая точка, находящаяся в ячейке пространства, занятой препятствием, пытаться найти соседнюю свободную ячейку и осуществлять поиск до нее.
  • public PathfindingResult { get; } - результат последнего успешного поиска пути.

21. Nav3DPath: Events

Для удобства отслеживания окончания поиска пути реализованы события:

  • public event Action OnPathfindingSuccess - срабатывает при успешном завершении поиска пути.
  • public event Action<PathfindingError> OnPathfindingFail - срабатывает при возникновении ошибки при поиске пути.
  • public event Action OnPathfindingComplete - срабатывает как при успешном, так и при неуспешном завершении поиска пути.

22. Nav3DPath: Dispose

После того как вы завершили работу с объектом Nav3DPath, необходимо вызвать метод public void Dispose(). необходимо вызвать метод public void Dispose(). Это необходимо для удаления пути из хранилища препятствий. В противном случае при добавлении/обновлении/удалении какого-либо препятствия, путь будет проверяться на необходимость обновления, что будет занимать вычислительные ресурсы. Любые пути, инициализированные на сцене, для которых не был вызван Nav3DPath , будут занимать вычислительные ресурсы.

23. PathfindingError

Содержит сведения об ошибке в случае срабатывания _OnFail колбэка.

Свойства:

  • public PathfindingResultCode Reason причина неудачи поиска пути
    Возможные значения свойства:
ValueОписание
SUCCEEDEDПоиск пути завершился успешно.
PATH_DOES_NOT_EXISTМежду точками не существует пути. Это возможно если хотя бы одна из точек окружена препятствиями со всех сторон.
TIMEOUTПоиск пути занял больше времени чем разрешено и был прерван.
CANCELEDПоиск пути был завершен по указанию пользователя, или по внутренней логике Nav3D.
START_POINT_INSIDE_OBSTACLEПоиск пути не удался, потому что начальная точка пути находится внутри препятствия
TARGET_POINT_INSIDE_OBSTACLEPathfinding has been canceled because the target point of the path is inside an obstacle.
UNKNOWNВнутренняя ошибка.
  • public string Msg сообщение с более подробной информацией об ошибке.

24. PathfindingResult

Хранит результаты поиска пути и временные затраты.

Временные затраты поиска пути:

    • public TimeSpan PathfindingDuration { get; } - длительность выполнения поиска пути (A*).
    • public TimeSpan OptimizingDuration  { get; } - длительность выполнения оптимизации пути.
    • public TimeSpan SmoothingDuration   { get; } - длительность выполнения сглаживания пути.

Результаты поиска пути:

    • public Vector3[] RawPath { get; } - найденный путь после работы алгоритма A*
    • public Vector3[] PathOptimized { get; } - путь после применения алгоритма оптимизации.
    • public Vector3[] PathSmoothed  { get; } - путь после применения алгоритма сглаживания к оптимизированному пути. Если Smooth = false, то содержимое будет идентично PathOptimized.
    • public int[] TargetIndices { get; } – the indices of the target points in the PathSmoothed array. The target points mean the points used when calling Nav3DPath.Find().
    • public PathfindingResultCode Result { get; } - код результата поиска.

25. Usage example

Ниже приведен пример использования Nav3DPath.

				
					using Nav3D.API;
using System;
using System.Linq;
using UnityEngine;

class YourGameScenario : MonoBehaviour
{
   #region Attributes

   Vector3[] m_FoundPath;

   #endregion
  
   #region Unity events

   void Start()
   {
       Nav3DManager.OnNav3DInit += () =>
       {
           Vector3 a = new Vector3(-10, -10, -10);
           Vector3 b = new Vector3(10, 10, 10);

           FindPath(a, b, PrintPath);
       };
   }

   void OnDrawGizmos()
   {
       if (!Application.isPlaying || !enabled)
           return;

       if (m_FoundPath != null && m_FoundPath.Any())
       {
           for (int i = 0; i < m_FoundPath.Length - 1; i++)
               Gizmos.DrawLine(m_FoundPath[i], m_FoundPath[i + 1]);
       }
   }
  
   #endregion

   #region Service methods

   //your method for pathfinding from A to B
   void FindPath(Vector3 _A, Vector3 _B, Action<Vector3[]> _OnPathFound)
   {
       //create Nav3DPathPath instance
       Nav3DPath path = new Nav3DPath(gameObject.name);

       //perform pathfinding from _A to _B
       path.Find(
               _A,
               _B,
               _OnSuccess: () =>
               {
                   //notify that path was found
                   Debug.Log("Path successfully found!");

                   //invoke callback
                   _OnPathFound(path.Trajectory);

                   //finish work with Nav3DPath instance
                   path.Dispose();
               }
           );
   }

   void PrintPath(Vector3[] _Path)
   {
       m_FoundPath = _Path;

       Debug.Log($"Path points: {string.Join(", ", m_FoundPath)}");
   }

   #endregion
}

				
			

26. Nav3DPathTester

Мы реализовали специальный компонент (Nav3DPathTester), который может быть использован при построении игровых сцен для проверки того, как будет проходить путь в разных местах сцены.

  • Для его использования вам надо добавить на любой игровой объект на сцене компонент Nav3DPathTester.
  • Для его работы система Nav3D должна быть инициализирована, так что его применение возможно только в игровом режиме.

После добавления компонента вы увидите его инспектор:

Здесь смысл всех параметров соответствует смыслу параметров метода Nav3DPath.Find() .

Добавьте на игровую сцену несколько игровых объектов, которые будут служить в качестве точек между которыми будет искаться путь. Далее добавьте эти объекты в список Targets в инспекторе Nav3DPathTester.

В игровом режиме, при включенном Gizmos вы сможете увидеть как путь пройдет через все объекты Targets.

Ниже показаны два примера тестового пути для трех объектов при выключенной и включенной опцией Loop.

27. Nav3DAgentManager

В этом классе доступны методы получения списка агентов на сцене, находящихся в некоторой области:

  • public static Nav3DAgent[] GetAgentsInBounds(Bounds _Bounds) - получить список агентов Nav3DAgent, находящихся в Bounds.
  • public static Nav3DAgent[] GetAgentsInSphere(Vector3 _Center, float _Radius) - получить список агентов Nav3DAgent, находящихся в сфере с центром в _Center, радиусом _Radius.

28. Nav3DAgentConfig

Nav3DAgentConfig служит описанием агента и позволяет настраивать его поведение и все необходимые параметры.

Вы можете создать экземпляр через контекстное меню вкладки Проект.

После создания описания в инспекторе вы увидите следующий список групп параметров:

Приведем пояснение назначения параметров и их допустимые величины.

Behavior

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Motion Navigation Type
MotionNavigationType
enum MotionNavigationType
COMBINED, GLOBAL, LOCAL

Основное назначение всех агентов - движение к какой-либо точке в пространстве. Агенты могут двигаться с помощью трех способов ориентирования в пространстве.

  • Используя глобальный путь (GLOBAL). В таком случае агент выполнит поиск пути и будет двигаться по нему, невзирая на внешние условия (другие агенты, находящиеся слишком близко края препятствий).
  • С использованием только локального уклонения (LOCAL). Агент не будет использовать поиск пути для движения, а будет двигаться к цели по прямой, попутно уклоняясь от других агентов и препятствий, когда они встречаются на курсе движения. Разумеется не всякое препятствие может быть преодолено таким образом.
  • Наконец, агент может осуществлять движение к цели используя поиск пути и локальное уклонение одновременно (COMBINED). Агент будет двигаться по найденному пути и уклоняться от подошедших близко других агентов, а также находящихся слишком близко препятствий.

Radius

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Radius
Radius
float
>0

Радиус агента используется для осуществления маневров локального уклонения. Установление корректного радиуса важно для эффективного выполнения локального уклонения как самим агентом, так и прочими агентами поблизости. Советуем настраивать радиус так, чтобы все визуальное содержимое игрового юнита, коим является агент, находилось внутри сферы.

Speed

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Speed
Speed
float
>0

Скорость движения агента. Можете менять ее в любой момент времени, если потребуется.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Max Speed
Max Speed
float
>Speed

Максимальная скорость агента. Этот параметр нужен для выполнения локального уклонения. В некоторых ситуациях агенту может потребоваться ускориться, чтобы избежать столкновения. Если значение будет слишком велико, то порой агент может двигаться рывками при выполнении локального уклонения. Так что советуем выставлять максимальную скорость чуть больше чем Speed(больше менее чем в полтора раза).

Для вашего удобства в инспекторе имеется два способа установления этого значения. С помощью конкретного значения. Либо с помощью множителя для Speed. Советуем использовать множитель, для того чтобы максимальная скорость зависела от Speed агента. Тогда MaxSpeed будет меняться вслед за изменением Speed

Local avoidance

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Agents considered number limit
Agents considered number limit
bool
true, false

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

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Agents number
ConsideredAgentsNumberLimit
int
>=1

Количество агентов, которые берутся в рассмотрение из всех ближайших агентов.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Avoid static obstacles
AvoidStaticObstacles
bool
true, false

Нужно ли выполнять локальное уклонение от статических препятствий

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

Не рекомендуется включать эту возможность без надобности, поскольку она оказывает нагрузку на производительность.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
ORCA Tau
ORCATau
float
>0

Временной диапазон вычисления скоростного препятствия. Не рекомендуем менять этот параметр

Лучше понять его смысл вам поможет оригинальная статья по ORCA Reciprocal n-body Collision Avoidance. Jur van den Berg, Stephen J. Guy, Ming Lin, and Dinesh Manocha

Поиск пути

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Pathfinding timeout (ms)
PathfindingTimeout
int
>0

Максимальное время, отведенное на выполнение поиска пути. При превышении этого времени поиск(pathfinding) будет отменен, и будет вызван колбек _OnPathfindingFail.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Smooth the path
SmoothPath
bool
true, false

Нужно ли сглаживать найденный путь.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Samples per min bucket volume
SmoothRatio
int
>0

Количество сегментов пути на один минимальный объем октодерева, получаемых при сглаживании исходного пути. Не следует избыточно увеличивать этот параметр, так как это увеличивает итоговое время поиска пути.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Auto-update path on stagnant behavior
AutoUpdatePath
bool
true, false

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

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

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Auto-update cooldown (ms)
PathAutoUpdateCooldown
int
>=1

Минимальный период автокорректировки пути. Если область пространства будет слишком заполнена другими агентами, то пересчет пути может быть слишком частым, что негативно повлияет на производительность в случае большого количества агентов на сцене. Рекомендуем ограничить частоту автокорректировки несколькими секундами.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Try reposition target if occupied
TryRepositionTargetIfOccupied
bool
true, false

Включение параметра позволит совершить попытку поиска пути до соседней свободной ячейки, если целевая точка оказалась в ячейке, занятой препятствием.

Если параметр выключен, тогда в таком случае поиск пути будет прерван с ошибкой GOAL_POINT_INSIDE_OBSTACLE .

Motion

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Target reach distance
TargetReachDistance
float
>=0

Расстояние достижения цели. Когда вы отдаете агенту приказание достичь какой-либо цели, цель будет считаться достигнутой, когда pivot агента совпадет с координатой цели (расстояние между ними будет равным 0). Это может быть неудобно, если целью является объект с мешем, допустим планета в космосе. В таком случае выставьте этот параметр равным сумме радиуса видимой части агента и радиуса планеты. Тогда агент остановится, достигнув поверхности планеты.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Max rotation in degrees per fixed update tick
MaxAgentDegreesRotationPerTick
float
>=0

Максимальное количество градусов, на которое может повернуться агент при выполнении поворота в сторону движения.
В процессе движения агент поворачивается в сторону вектора скорости. Если вектор скорости круто меняется в процессе движения, то поворачивание агента может выглядеть резким. Чтобы сделать его более плавным, выставите этот параметр не слишком большим.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Rotation vector lerp factor
RotationVectorLerpFactor
float
(0 - 1)

In order to make the rotation of an agent even more smoother, when computing the rotation vector the frame rotation vector and the value of rotation vector for a few last frames are used.

Decreasing the parameter makes the rotation smoother, increasing it makes it sharper.

Velocity blending

При использовании глобального поиска пути и локального уклонения агент двигается, используя три вектора скорости:

  1. Вектор скорости следования по пути.
  2. Вектор скорости уклонения от агентов.
  3. Вектор скорости уклонения от препятствий.

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

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

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

Ниже приведены пояснения для параметров весов. Обратите внимание, что для каждой ситуации используются отдельные параметры

Все веса задаются типом float и должны иметь значение более 0

Соответствующие названия свойств в Nav3DAgentConfig:

  • PathVelocityWeight
  • PathVelocityWeight1
  • PathVelocityWeight2
  • AgentsAvoidanceVelocityWeight
  • AgentsAvoidanceVelocityWeight1
  • AgentsAvoidanceVelocityWeight2
  • ObstacleAvoidanceVelocityWeight
  • ObstacleAvoidanceVelocityWeight1
  • ObstacleAvoidanceVelocityWeight2

Debug

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Use log
UseLog
bool
true, false

Нужно ли логгировать работу агента.

Параметр Свойство в Nav3DAgentConfig Тип Диапазон значений
Log records count
LogSize
int
>0

Размер лога.

28.1 Creating and configuring a config via code

Все параметры Nav3DAgentConfig также могут быть заданы из кода.

Для этого вам надо создать экземпляр Nav3DAgentConfig задать нужные значения параметров, затем применить экземпляр к агенту.

  • Предлагается использовать свойство Nav3DAgentConfig.DefaultConfig для создания нового экземпляра.
  • Для получения копии экземпляра предназначен метод Copy() .
  • Для применения конфига к агенту есть метод Nav3DAgent.SetConfig(Nav3DAgentConfig _Config) .

Ниже приведен пример создания экземпляра Nav3DAgentConfig и его применения к агенту.

				
					void ConfigureAgentConfig()
{
   Nav3DAgent myAgent = GetComponent<Nav3DAgent>();

   //create Nav3DAgentConfig instance with default parameters
   Nav3DAgentConfig myConfig = Nav3DAgentConfig.DefaultConfig;

   //set the parameters you want
   myConfig.Radius = 1.2f;
   myConfig.MotionNavigationType = MotionNavigationType.LOCAL;

   //apply config to agent
   myAgent.SetConfig(myConfig.Copy());
}

				
			

29. Nav3DAgent: Methods

Как упоминалось выше, вы можете использовать скрипт Nav3DAgent в качестве компонента для вашего игрового объекта и обращаться к нему через GetComponent() .

Для управления Nav3DAgent реализованы следующие публичные методы:

  • установка Nav3DAgentConfig.
				
					public void SetConfig(Nav3DAgentConfig _Config)
				
			
  • Команда двигаться к точке.
				
					public void MoveTo(
Vector3                  _Point,
Action                   _OnReach           = null,
Action<PathfindingError> _OnPathfindingFail = null,
float?                   _ReachDistance     = null)
				
			

Параметры:

    • Vector3 _Point - целевая точка.
    • Action _OnReach - колбэк достижения целевой точки.
    • Action<PathfindingError> _OnPathfindingFail - колбэк ошибки поиска пути.
    • float? _ReachDistance - расстояние до целевой точки, необходимое для завершения следования и срабатывания _OnFinished.
  • Команда последовательно двигаться по списку точек. Будет найден путь, проходящий через каждую точку массива.
				
					public void MoveToPoints(
Vector3[]                _Points,
bool                     _Loop                  = false,
bool                     _StartFromClosest      = false,
bool                     _SkipUnpassableTargets = false,
float?                   _ReachDistance         = null,
Action<Vector3>  _OnTargetPointPassed           = null,
Action                   _OnFinished            = null,
Action<PathfindingError> _OnPathfindingFail     = null)

				
			

Параметры:

  • Vector3[] _Points – a target points.
  • bool _Loop - замыкать ли движение по точкам. Если true, агент будет двигаться по последовательности точек бесконечно, переходя к первой каждый раз при достижении последней.
  • bool_StartFromClosest - начинать ли движение с ближайшей точки массива, а не с первой.
  • bool_SkipUnpassableTargets - будет ли пропускаться каждая точка, до которой поиск пути завершился с ошибкой. Если параметр установлен в false, то при неудаче поиска пути между любой парой точек, будет выполнен _OnFail колбэк, и поиск будет прекращен.
  • float? _ReachDistance - расстояние до целевой точки, необходимое для завершения следования и срабатывания _OnFinished.
  • Action<Vector3> _OnTargetPointPassed - колбэк, срабатывающий при прохождении агентом одной из целевых точек пути.
  • Action _OnFinished - колбэк, срабатывающий при прохождении агентом последней точки пути. Колбэк не сработает, если _Loop = true.
  • Action<PathfindingError> _OnPathfindingFail - колбэк ошибки поиска пути.
  • Начать преследование transform цели.

				
					public void FollowTarget(
Transform                _Target,
bool                     _FollowContinuously,
float                    _TargetOffsetUpdate,
float                    _TargetReachDistance   = 0,
Action                   _OnReach               = null,
Action                   _OnFail                = null,
Action<PathfindingError> _OnPathfindingFail     = null)

				
			

Параметры:

    • Transform _Target - цель для преследования.
    • bool _FollowContinuously - преследовать ли цель без окончания. Если true, то агент никогда не прекратит преследование и не вызовет _OnReach. При достижении цели просто будет находиться рядом, пока цель снова не отдалится.
    • float _TargetOffsetUpdate - величина смещения цели, для которой наступит перерасчет пути до цели.
    • float _TargetReachDistance - расстояние до transform цели, необходимое для завершения преследования и срабатывания _OnReach.
    • Action _OnReach - колбэк достижения цели преследования.
    • Action _OnFail - колбэк, срабатывающий в случае если transform цели был уничтожен или переведен в неактивное состояние на сцене.
    • Action<PathfindingError> _OnPathfindingFail - колбэк ошибки поиска пути.
  • Останавливает выполнение текущей действующей команды
				
					public void Stop()
				
			
  • Возвращает агентов, удовлетворяющих предикату, находящихся в заданном радиусе от агента.
				
					public Nav3DAgent[] GetAgentsInRadius(float _Radius, Predicate<Nav3DAgent> _Predicate = null)
				
			

Примеры по использованию Nav3DAgent вы можете найти в демо сценах, расположенных в папке Nav3D/Demo.

30. Nav3DAgent: Debug

У Nav3DAgent реализован инспектор, предоставляющий несколько полезных функций, помогающих в отладке и дающих лучшее понимание о взаимодействии объектов на сцене.

30.1 Debug drawing

В первой секции вы можете визуализировать агента и его ближайшее окружение. Делать это следует со включенным отображением Gizmos на сцене:

1.Визуализация радиуса агента.

2. Визуализация нормализованных скоростей агента.

Желтый - вектор скорости следования по глобальному пути (вектор направления от положения агента к следующей целевой точке на пути).

Зеленый - вектор скорости локального уклонения.

Синий - результирующий вектор движения (смесь вектора следования по пути и вектора локального уклонения).

3. Визуализация пути, по которому следует агент.

4. Визуализация близлежащих агентов, которые могут быть учтены при выполнении локального уклонения.

При выполнении локального уклонения в зависимости от настройки допустимого количества рассматриваемых агентов (в описании агента) будет взято n ближайших агентов из всех близлежащих агентов.

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

6. Всё сразу

30.2 Agent log

Тут вы можете скопировать в буфер обмена содержимое лога агента нажав на кнопку, если логирование включено в описании агента.

31. Nav3DEvader

Мы реализовали отдельный контроллер, поведение которого состоит в уклонении от находящихся рядом агентов, и статических препятствий, если вдруг он попал в соприкосновение с ними.

Его поведение выглядит довольно интересно, и продемонстрировано в демо Nav3D/Demo/EvadersCrowd.

В инспекторе компонента имеются следующие настройки:

  • Radius - радиус, для которого проверяется пересечение с другими агентами и прочими сущностями.
  • Max Speed - максимально возможная скорость при выполнении избегания столкновения.
  • Speed Decay Factor - множитель затухания скорости после завершения избегания. Чем больше значение, тем быстрее остановится Nav3DEvader после избегания столкновения. допустимое значение в диапазоне (0 - 1).

32. Nav3DSphereShell

Представляет собой сферическую оболочку, которая воспринимается агентами как объект для уклонения. Nav3DSphereShell может приводиться в движение извне, агенты на сцене, а также Nav3DAgents and Nav3DEvader, будут уклоняться от столкновения с ним.

Поведение Nav3DSphereShell продемонстрировано в демо Nav3D/Demo/SphereShellDemo.

В инспекторе компонента вы можете настроить радиус сферы.

Nav3DSphereShell

Represents a spherical shell that is perceived by other agents as an object to a...

Nav3DEvader

There is also a separate controller, whose behavior consists of just avoiding ne...

Nav3DAgentManager

This class implements several methods to get a list of all Nav3DAgents located i...

Nav3DPathTester

We implemented a useful component (Nav3DPathTester), which can be used while bui...

PathfindingResult

Contains the pathfinding data and time statistics. Time statistics: public TimeS...

Nav3DPath: События

For the convenience of notification when the pathfinding finished, the following...

Лог агента

Here you can copy the contents of the agent log to the clipboard by clicking the...

Debug drawing

In this section, you can visualize the agent and his nearest environment. This s...

Создание и настройка конфига из кода

All Nav3DAgentConfig parameters can be configured through the code as well. To ...

Nav3DManager

Nav3DManager is a helper static class. Can be useful for checking whether Nav3D ...

Nav3DInitializer

To use Nav3D in playmode, you need to initialize it. The Nav3DInitializer compon...

Nav3DObstacleLoader

To use the possibility of pre-baking obstacles on the scene in editor mode and t...

Chat Icon Close Icon
ru_RURussian