{"id":2438,"title":"\u041a\u0430\u0440\u0442\u0430 \u00ab\u0422\u0438\u043d\u044c\u043a\u043e\u0444\u0444\u00bb, \u0437\u0430 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u043b\u0430\u0442\u0438\u0442\u044c","url":"\/redirect?component=advertising&id=2438&url=https:\/\/vc.ru\/promo\/257524-tinkoff-black&placeBit=1&hash=6ac193f58270cd0abaa01d2bebe1c84cd0cb48b07c4d1385b9ef23dd9094eae0","isPaidAndBannersEnabled":false}
Unreal Engine
Superyateam

ИИ для машин быстро и просто

Салют DTF! Надеюсь, ты с пользой проводишь карантин и разрабатываешь новые игры? Мой туториал об ИИ для машин в Unreal Engine может помочь.

Из коробки в UE4 ИИ доступен только для персонажей. Всё остальное нужно делать самому. В том числе машины. Об этом и будет туториал.

Заготовка

Пусть наш учебный проект будет самым простым. Поэтому используем Advanced Vehicle C++ Template шаблон.

1. Player Pawn

Начнем с Player Pawn. Это не обязательный шаг, просто мне нравится вид сверху — оттуда все хорошо видно. Создадим blueprint на основе класса Pawn и определим его следующим образом:

​BP_Player blueprint

Добавим SpringArm компонент и Camera component. Настройте их так, как вам нравится. Мой вариант:

Добавим также FloatingPawnMovement компонент, иначе камера не будет двигаться.

С уровня удалим все PlayerStart объекты и на машине уберем галочку со свойства AutoPossesPlayer. А на объекте нового типа BP_Player, это свойство выставим в значение Player 0. Теперь при запуске игры мы сможем управлять камерой при помощи WASD. А мышкой дальше будем пользоваться чтобы давать команду машине.

2. Настройка ИИ

Теперь ИИ. Нам нужен AIController:

Не пинайте за Cast в обработчике Event Tick ​

И Blackboard с одной переменной ClickLocation типа Vector. И, наконец, Behavior Tree:

В Behavior Tree только одна команда Move To с параметром ClickLocation, который мы определили и проинициализировали раньше.

Последний обязательный пункт: добавим NavMeshBoundsVolume на уровень, иначе PathFollowingComponent не будет работать.

Чтобы не тратить время, я пока не вдавался в детали. Но если что-то непонятно — пишите в комментариях.

Если бы мы делали ИИ для персонажей, то он бы уже заработал. Но с машинами все сложнее.

ИИ машины

Разберемся как работает Move To команда в UE4.

Диаграм​ма ок?

Когда Behavior Tree запускает команду Move To, оно на самом деле выполняет метод AAIController::MoveTo. Затем управление переходит в модуль AIModule, который в итоге вызывает метод UNavMovemementComponent::RequestDirectMove.

Только UCharacterMovementComponent реализует этот метод. Поэтому настроить ИИ для персонажей так просто в UE4. Для всего остального разработчикам придется потрудиться самим.

Сигнатура метода выглядит так:

void RequestDirectMove(const FVector& MoveVelocity, bool bForceMaxSpeed)

Параметр MoveVelocity — это вектор скорости, направленный в сторону цели. Если умножить скорость на DeltaTimeSeconds, то мы получим вектор расстояния до цели. И с ним работать уже намного проще.

Путь до цели состоит из сегментов. И если мы движемся не по последнему, то bForceMaxSpeed равен true. AIModule как бы говорит нам: «Гони по максимуму, до цели еще далеко!».

Итак, сделаем свой movement компонент c именем UAIVehicleMovement. Отнаследуем его от UWheeledVehicleMovementComponent4W и переопределим RequestDirectMove метод:

Super::RequestDirectMove(MoveVelocity, bForceMaxSpeed); FVector VehicleLocation = GetOwner()->GetActorLocation(); FVector Destination = VehicleLocation + MoveVelocity * GetWorld()->GetDeltaSeconds(); DrawDebugLine(GetWorld(), GetOwner()->GetActorLocation(), Destination, FColor::Red, false, 1.f, 0, 3.f);

И изменим конструктор класса машины так, чтобы он использовал новый movement компонент:

// declaration: AVehicleAIPawn(const FObjectInitializer& ObjectInitializer); // definition: AVehicleAIPawn::AVehicleAIPawn(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer.SetDefaultSubobjectClass<UAIVehicleMovement>(AWheeledVehicle::VehicleMovementComponentName))

Запустим игру. Если вы выполнили все шаги правильно, то после клика мышкой на карте, мы увидим сферу на месте клика и красную линию — дистанцию от машины до клика.

ПИД-регулятор

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

Есть, наверно, много способов реализовать движение машины из точки А в точку Б. Я использовал ПИД-регуляторы. Я не смогу понятно объяснить, как они работают. Там много математики и куча вещей, которые я сам не понимаю до конца. Но вот эта хорошая статья мне здорово помогла:

Я прочитал статью, покопался в интернете и реализовал свой ПИД-регулятор вот таким образом:

Если по коду что-то непонятно — задавайте вопросы.

Вот так все выглядит в действии:

p.s. Эта статья — перевод. Оригинал я написал в своем блоге на английском языке: https://superyateam.com/2020/04/18/how-to-implement-vehicle-ai-in-ue4. Подписывайтесь, раз в месяц я пишу статьи про геймдев и UE4.

{ "author_name": "Superyateam", "author_type": "self", "tags": [], "comments": 5, "likes": 23, "favorites": 54, "is_advertisement": false, "subsite_label": "unrealengine", "id": 126291, "is_wide": true, "is_ugc": true, "date": "Sun, 19 Apr 2020 09:56:23 +0300", "is_special": false }
0
5 комментариев
Популярные
По порядку

Неужели cast такой прожорливый, что за него нужно извиняться?

0

Вроде да. Плюс это можно сделать один раз, в begin play например. И не кастить потом каждый тик

0

Это да, просто интересно насколько дела плохи с кастом

0

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

1

SteeringInput скрывает член класса, а при замене названия, блупринты теряют физику, и меши машин просто вращаются вокруг точки Actor'а. Есть решение?

0
Читать все 5 комментариев
{"hash":"43f98b2b","params":{"id":"dtfru","service":1,"title":"\u041f\u0440\u044f\u043c\u043e\u0439 \u044d\u0444\u0438\u0440","isLegacy":false}}