Все Гайды Мой Кабинет

Поиск пути и обход препятствий с помощью NavMesh

Автор: Admin 1 месяц назад

Приветствую! В данной статье мы научимся работать с NavMesh, который двигает объект к определённой точке по самому кратчайшему пути, огибая элементы препятствий. И разберём мы работу NavMesh-а на примере 3D игры, видом сверху.

Для начала подготовим нашу сцену:

  • Создайте объект земли, по которому будет передвигаться персонаж, дав ему название Ground. (3D Object - Plane).
  • Создайте объект главного персонажа, дав ему название Player. (3D Object - Cube).
  • Создайте несколько объектов препятствий, которые наш персонаж будет обходить. Дайте им название Barier. (3D Object - Cube).

Должно выглядеть примерно так.

Работу с NavMesh-ем можно условно разделить на две части:

  • Создание Агента для NavMesh, который будет ходить по местности. Этим агентом будет Ваш персонаж, то-есть объект Player.
  • Создание самого NavMesh, по которому будет ходить Агент. В неё входит не только объект земли Ground, но и все препятствующие элементы Barier, которые будет обходить Агент.

И для начала начнём с создания Агента. Для этого нам необходимо с помощью окна Inspector добавить компонент Nav Mesh Agent для того объекта, который и будет производить все наши движения, в нашем случае, это объект Player. Так же обратите внимание, что после добавления данного компонента, у объекта появляются слабозаметные границы в форме цилиндра.

В окне Inspector в полях Radius и Height укажите такие значения, чтобы ваш объект полностью входил в область данного цилиндра, и не выходил за её пределы. У меня эти значения получились такими. Radius: 0.75, Height: 1.

Агента для NavMesh мы создали, теперь необходимо создать сам NavMesh. Для этого переходим во вкладку Window - AI - Navigation, и после этого откроется окно Navigation, которое будет автоматически встроено рядом с окном Inspector.

В настройках окна Navigation нам необходимо указать, что по объекту Ground можно ходить, а в местах, где стоят объекты Barier - нельзя. И первым делом начнём с объекта Ground.

В окне Hierarchy выбираем наш объект земли Ground, и потом в окне Navigation производим для данного объекта следующие действия:

  • Выбираем вкладку Object.
  • Ставим галочку в поле Navigation Static.
  • В поле Navigation Area указываем Walkable.

Теперь производим настройки для наших объектов-препятствий, которые наш персонаж должен обходить. Всё почти тоже самое. В окне Hierarchy выбираем сразу ВСЕ объекты препятсвий, и во вкладке Navigation производим для них следующие действия:

  • Заходим во вкладку Object.
  • Ставим галочку Navigation Static.
  • А в поле Navigation Area ставим Not Walkable.

Остались все эти настройки запечь. Для этого переходим во вкладку Bake, и в полях Agent Radius и Agent Height указываем те значения, которые мы указывали в агенте. Напомню, у меня эти значения были: Radius = 0.75, Height = 1. После чего жмём кнопку Bake.

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

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

Создадим c# скрипт, и назовём его Player. Заранее присвойте его нашему объекту Player, и впишите в скрипт следующий код:

using UnityEngine;
using UnityEngine.AI;

public class Player : MonoBehaviour
{
    private NavMeshAgent myAgent;

    private void Start()
    {
        myAgent = GetComponent<NavMeshAgent>();
        myAgent.SetDestination(new Vector3(-0.5f, 0, -9.7f));
    }
}

В строке #6 мы создали переменную myAgent, в которой будем хранить ссылку на наш компонент NavMeshAgent. А уже в строке #10 мы эту ссылку получаем. Строкой ниже, с помощью метода SetDestination() мы двигаем персонажа по указанным координатам (-0.5f, 0, -9.7f). Для примера эти координаты можете изменить на любые другие. Так же обратите внимание, что во второй строке для работы NavMesh мы дописали библиотеку UnityEngine.AI.

Так же хочу обратить Ваше внимание на то, что благодаря методу SetDestination(), нет необходимости самому писать скрипт передвижения персонажа. Данный метод делает это за вас. Помимо передвижения, он поворачивает персонажа в сторону движения, заносит персонажа на поворотах, и делает много других интересных вещей. Всё это настраивается в компоненте NavMeshAgent в отделе Steering.

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

Давайте немножко перепишем наш код:

using UnityEngine;
using UnityEngine.AI;

public class Player : MonoBehaviour
{
    private NavMeshAgent myAgent;

    private void Start()
    {
        myAgent = GetComponent<NavMeshAgent>();
    }

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            RaycastHit placeInfo;
            if(Physics.Raycast(ray, out placeInfo))
            {
                myAgent.SetDestination(placeInfo.point);
            } 
        }
    }
}

Давайте же посмотрим, что же мы тут дописали?

  • Мы добавили метод Update(), поскольку нам передвигать персонажа нужно не единожды, а постоянно.
  • Далее, с помощью метода GetMouseButtonDown() мы проверяем, была ли нажата левая кнопка мыши, и если да, то с помощью свойства mousePosition и метода ScreenPointToRay() получаем луч, и заносим в переменную ray.
  • Чуть ниже, с помощью метода Raycast() мы выпускаем полученный ранее луч, чтобы найти координаты той точки, на которую мы кликнули, и заносим их в переменную placeInfo.
  • Ну а далее как и в прошлый раз, с помощью метода SetDestination() передвигаем нашего персонажа в ту точку пространства, куда был произведён клик мыши.

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

И да, в одном из предыдущих статей я отдельно объяснял, как осуществлять передвижение персонажа по клику мыши в Unity 3D, но без использования NavMesh, а следовательно, и без обхода препятствий. Поэтому, думаю будет очень полезным ознакомиться с данным гайдом.

Если есть какие вопросы, пишите в комментариях. А они точно будут, так как NavMesh довольно большая тема, все детали которой сложно охватить в одной статье.

Вы можете отблагодарить автора донатом. Донат

Комментарии

0
Будьте первым, кто оставит комментарий к этому посту
Гости не могут оставлять комментарии. Войдите на Сайт или Зарегистрируйтесь