Поиск путей
Для перемещения ИИ-персонажей по игровому миру в Unity существует набор специальных инструментов под названием NavMesh, который предназначен, чтобы создавать целые “навигационные” карты в игровом мире. Система позволяет находить самые сложные пути для перемещения в заданную точку и при этом обходить препятствия.
Принцип работы NavMesh
Теперь попробуем разобраться с возможностями, которые дает эта система.
В первую очередь, для поиска путей и создания карт “навигаций”, сцена должна специально быть подготовлена. В 2D играх используется двумерная сетка, проще говоря, массив точек по которым персонаж может перемещаться. Для 3D проектов необходимо создавать специальную отдельную сетку, которая должна учитывать, помимо длины и ширины сцены, еще и ее высоту.
В Unity уже есть стандартный набор необходимых инструментов для создания карт “навигаций”, все они находятся в разделе Navigation.
Эти стандартные инструменты позволяют создавать простейшие карты на любой горизонтальной поверхности.
В этой статье мы будем использовать расширенный набор инструментов в дополнение к стандартному Navigation.
Для этого необходимо будет скачать специальный архив. Ссылку на архив можно найти в разделе Bake окна Navigation.
Либо можете загрузить архив перейдя по этой ссылке.
Из всего архива нам понадобятся только папки которые находятся в разделе Assets. Переносим эти папки в проект и после сохранения возвращаемся в unity.
Теперь можно приступить к созданию системы навигации, для этого достаточно будет создать любую горизонтальную поверхность на сцене.
Для примера воспользуемся обычным Plane, хотя можно и просто создать любой Cube и растянуть его до нужных размеров.
После того как создали поверхность на сцене, необходимо добавить ей компонент NavMeshSurface.
Этот компонент позволяет создавать карты “навигации” на поверхностях. Переходим в настройки компонента.
Из всего набора доступных параметров компонента NavMeshSurface нам понадобится только кнопки Clear и Bake в самом низу перечня настроек.
Кнопка Bake позволяет подготовить или “запечь” карту на поверхностях, с учетом размера самой поверхности и характеристик объекта, что будет перемещаться по этой поверхности.
Нажимаем кнопку Bake и смотрим на результат, который получился после “запекания”.
Готовая карта отображается как тонкая полупрозрачная синяя поверхность поверх объекта.
Теперь поверхность готовая чтобы по ней могли перемещаться юниты. Для этого можно добавить любой объект, например, воспользуемся обычным 3D Capsule после чего сразу добавляем ему компонент NavMeshAgent.
Компонент NavMeshAgent необходим, чтобы находить пути по готовым картам “навигации”.
Также компонент обладает стандартными настройками, чтобы перемещать юнит по найденным путям на карте.
Поэтому настройки компонента NavMeshAgent можно оставить без изменения. Далее, чтобы можно было указывать точку куда необходимо отправить юнит, добавим ему еще один компонент ClickToMove.
Компонент ClickToMove позволит игроку мышкой указывать точку куда следует двигаться юниту. После всех этих действия можно запустить проект и проверить работу компонентов.
Из записи выше, можно увидеть как юнит перемещается в точку куда указал игрок. Чтобы немного усложнить путешествие юниту добавим на поверхность препятствие.
После добавления препятствия на поверхность, нужно ее снова “запечь” с помощью компонента NavMeshSurface.
Теперь можно увидеть как выглядит новая карта после “запекания” с учетом препятствия на ней.
Снова запускаем проект и отправляем юнита путешествовать по поверхности.
Теперь юнит двигается по поверхности обходя препятствие на ней.
Заключение
Данный способ работы с NavMesh позволяет создавать простые карты “навигации” для любых горизонтальных поверхностей на сцене. Также можно изменять характеристики юнита, чтобы создавать более сложные карты.
Часто бывает так что поверхности по которым могут двигаться юниты разделены между собой, поэтому рассмотрим способ соединения разных поверхностей между собой в одну карту.
Для этого создадим несколько разных поверхностей, горизонтальных и вертикальных, по которым будет перемещаться юнит.
Сразу можно будет добавить несколько препятствий на поверхности, как делали это раньше для горизонтальной поверхности.
Далее снова добавляем горизонтальной поверхности компонент NavMeshSurface, после чего можно сразу будет ее “запечь”, чтобы создать карту.
Нажимаем кнопку Bake и видим, что “запеклись” сразу обе горизонтальные поверхности, поэтому добавлять компонент NavMeshSurface второй горизонтальной поверхности нет необходимости.
Теперь, чтобы создать карту на вертикальной поверхности, сначала необходимо ее подготовить. Для этого растягиваем поверхность до нужных размеров и разворачиваем под углом 90’ так, чтобы она пересекала обе горизонтальные поверхности.
После установки вертикальной поверхности на место, добавляем ей компонент NavMeshSurface и “запекаем” ее с помощью кнопки Bake.
Теперь у нас есть готовые карты для горизонтальных и вертикальных поверхностей, но так как карты принадлежать разным объектам которые разделены между собой необходимо их соединить с помощью специальных “мостов”.
Чтобы создать такой мост между поверхностями, добавим на сцену, в том месте где будет проходить соединение, пустой объект с одним компонентом NavMeshLink.
Настроить соединение достаточно легко: необходимо перетянуть начальную и конечную точку объекта NavMeshLink так, чтобы они находились у краев соединяемых поверхностей, после чего задаем ширину перехода Width в настройка компонента.
В самих настройках компонента NavMeshLink можно также указать тип перехода. Для примера укажем тип перехода Area Type как Walkable. Тип Walkable, в отличие от типа Jump, позволяет юниту переходить соединение между поверхностями, а не просто переступать его.
После того как закончили настраивать первое соединение NavMeshLink, переходим к настройкам второго “моста”, который соединит вертикальную и горизонтальную поверхности.
Готово. Дальше добавляем на сцену юнита, как это делали в прошлом примере с горизонтальной поверхностью. Добавляем юниту сначала компонент NavMeshAgent и компонент ClickToMove.
После чего можно запустить проект и посмотреть на результат.
Исходник проект можно загрузить по этой ссылке