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

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

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

Заготовка

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

1. Player Pawn

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

<i>​BP_Player</i> blueprint
​BP_Player blueprint

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

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

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

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

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

Не пинайте за Cast в обработчике Event Tick ​
Не пинайте за 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.

2828
7 комментариев

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

1
Ответить

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

Ответить

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

Ответить

Комментарий недоступен

Ответить

Я думаю тогда все по другому будет реализовано

Ответить