Уроки Unreal Engine

Unreal Engine 4. Учебник для начинающих, часть 9: Работа с Искусственным Интеллектом

В этом занятии, посвященном изучению Unreal Engine 4 вы узнаете, как создать игрового персонажа с ИИ, который может самостоятельно атаковать врагов. Кроме того, вы научитесь составлять ветки поведения для настройки Искусственного Интеллекта.

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

В Unreal Engine ИИ создается при помощи так называемого древа поведения, которое представляет собой целую систему с настройками и свойствами. Вы можете создать дерево поведения, чтобы персонаж сражался, если его здоровье больше 50% и убегал с поля боя, если оно менее 50%.

В этом уроке вы узнаете, как:

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

Это занятие является частью серии, которая состоит из 10 уроков, посвященных Unreal Engine:

Начало работы

В первую очередь вам необходимо скачать стартовый проект и все материалы, необходимые для работы. Разархивируйте файл и откройте MuffinWar.uproject.

Нажмите Play, чтобы начать игру – вам нужно распределить в огороженной области кексики:

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

Чтобы создать ИИ-персонажа, вам понадобятся три вещи:

  1. Тело — это физическая оболочка персонажа. В этом уроке в качестве тела выступает маффин.
  2. Душа- это сущность, управляющая персонажем. Это может быть игрок или ИИ.
  3. Мозг — это то, каким образом ИИ принимает решения. Для его настройки можно использовать несколько способов, в том числе код C ++, Blueprints или деревья поведения.

В этом уроке у вас уже есть тело, поэтому вам остается создать для него душу и мозг.

Для чего нужен Controller?

Controller (контроллер)- это нефизический объект, который может управлять персонажем.

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

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

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

Создание ИИ контроллера

Перейдите к CharacterMuffinAI и создайте новый класс Blueprint. Теперь вам нужно выбрать AIController в качестве parent class и назвать его AIC_Muffin:

Далее вам нужно приказать маффину использовать ваш новый ИИ контроллер. Для этого выполните CharactersMuffinBlueprints и откройте файл BP_Muffin.

Сейчас на панели «Details» будут отображаться настройки по умолчанию для Blueprint. Если это не так, то вам нужно выбрать Class Defaults на панели инструментов:

Перейдите на панель «Details» и найдите раздел «Pawn». Установите для AI Controller Class значение AIC_Muffin — это приведет к появлению нового контроллера, когда появится маффин:

Так как вы сами располагаете кексы по своему усмотрению, вам нужно установить Auto Possess AI на Spawned, чтобы обеспечить автоматическое управление AIC_Muffin и BP_Muffin:

Нажмите Compile и закройте BP_Muffin. Сейчас вам предстоит создать логику для управления поведением маффина. Для этой цели вы можете использовать деревья поведения.

Создание дерева поведения

Вам нужно выполнить действия CharactersMuffinAIAdd NewArtificial IntelligenceBehavior Tree, назвать созданное дерево BT_Muffin и открыть для редактирования.

Обзор редактора для дерева поведения

Редактор для дерева поведения содержит несколько рабочих областей:

  1. Behavior Tree: на этом графике размещаются узлы, создающие дерево поведения;
  2. Details: тут отображаются свойства выбранных узлов;
  3. lackboard: эта панель будет отображать кнопки Blackboard (подробнее об этом позже) и их значения.

Как и Blueprints, деревья поведения состоят из узлов. Существует четыре способа расположения узлов в деревьях поведения — первые два это задачи и композиты.

Что такое задачи и композиты?

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

Для выполнения задач вам необходимо использовать композиты. Дерево поведения состоит из множества ветвей (поведения) и в основе каждой ветви лежит какая-то ее составная. Различные типы композитов имеют разные способы выполнения своих дочерних узлов.

Например, у вас есть следующая последовательность действий:

Чтобы каждое действие выполнялось в определенной последовательности необходимо использовать инструмент Sequence. Посмотрите, как это выглядит на схеме редактора:

Примечание: В этом примере блоки «Sequence», «Move To Enemy», «Rotate Towards Enemy» и «Attack» могут рассматриваться как поведение для атаки врага.

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

Например, если игровой персонаж не может переместиться переместится к врагу, Move To Enemy не выполнится. Таким образом, Rotate Toward Enemy и Attack также не смогут быть выполнены. Если персонаж все же найдет способ приблизиться к врагу, все блоки будут выполнены в нужном порядке.

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

Перемещение в случайное место

Создайте следующую последовательность подключений:

Чтобы создать команду движения для персонажа, создайте MoveTo и подключите его к Sequence. Этот узел переместит игрового персонажа в указанное вами место локации:

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

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

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

Создание Blackboards

Blackboards — это активный элемент, единственная функция которого — хранить переменные (также известные, как ключи). То есть, это что-то вроде памяти ИИ. Существуют и альтернативные способы чтения и хранения данных, однако blackboards наиболее простой и удобный.

Чтобы создать blackboards вам нужно вернуться в Content Browser и выполнить действия Add NewArtificial IntelligenceBlackboard. Измените название на BB_Muffin и откройте его.

Редактор Blackboard

Редактор Blackboard состоит из двух рабочих панелей:

Blackboard: тут находится список всех ключей;

Blackboard Details: эта панель отображает свойства выбранного ключа.

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

Создание ключа местоположения

Поскольку вы используете местоположение в трехмерном пространстве, вам необходимо сохранить его как вектор. Нажмите New Key, выберите Vector и назовите его TargetLocation:

Далее вам нужно придумать способ создать случайное место и сохранить его. Для этого вы можете использовать третий тип узла дерева поведения: service.

Для чего нужен Service

Service — это специальные службы, которые чем-то напоминают задачи.

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

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

А теперь те же самые задачи, но уже с использованием service:

Создание Service

Вернитесь к BT_Muffin и нажмите New Service:

Таким образом вы создадите новый service и он автоматически откроется. Находясь в Content Browser измените название сервиса на BTService_SetRandomLocation.

Команда должна выполняться только в случае необходимости перемещения персонажа, поэтому нужно соединить service и MoveTo. Для этого откройте BT_Muffin и щелкнув правой кнопкой по MoveTo выполните ServiceBTService и установите значение Set Random Location:

Теперь BTService_SetRandomLocation будет задействован при каждой активации MoveTo.

Генерация случайного местоположения персонажа

Для начала откройте BTService_SetRandomLocation и создайте новый узел Event Receive Activation AI:

 

Примечание: существует еще один способ генерации случайного месторасположения персонажа. Для этого нужно использовать узел Event Receive Activation и также соединить его с BTService_SetRandomLocation.

Чтобы создать случайное местоположение, добавьте выделенные на изображении узлы и обязательно установите Radius = 500:

Примечание: GetRandomPointInNavigableRadius использует координаты (NavMesh), чтобы определить, является ли точка доступной для использования ее в навигации. В этом уроке уже имеются готовые NavMesh, которые можно использовать, перейдя в Viewport и выбрав Show ⇒  Navigation.

Кроме того, вы можете создать свой собственный параметр NavMesh, при помощи Nav Mesh Bounds Volume.

Далее вам необходимо сохранить новые координаты в пространстве. Есть два способа, чтобы указать системе, какой ключ использовать:

  1. Вы можете указать ключ, используя его имя в узле Make Literal Name
  2. Вы можете установить новую переменную в дереве поведения, указав ее имя в всплывающем меню.

Сейчас вы будете использовать второй способ. Создайте переменную Blackboard Key Selector и назовите ее BlackboardKey. Включите Instance Editable, чтобы переменная отображалась в меню выбора дерева поведения:

Далее вам нужно создать и разместить узлы, как на изображении ниже:

Резюмируя:

  1. Активация определенного события ИИ происходит, если выполняется MoveTo;
  2. GetRandomPointInNavigableRadius устанавливает случайное навигационное местоположение в пределах 500 единиц;
  3. Blackboard устанавливает значение BlackboardKey в случайном месте;

Чтобы сохранить результаты, нажмите Compile и закройте BTService_SetRandomLocation.

Выбор Blackboard

Откройте BT_Muffin и убедитесь, что у вас е выбран ни один объект. Перейдите к панели Details и установите значение поведения BB_Muffin для параметра Blackboard Asset:

Теперь MoveTo и BTService_SetRandomLocation получили автоматизированный параметр TargetLocation:

Запуск Дерева Поведения

Вам нужно открыть AIC_Muffin и подключить дерево поведения к событию BeginPlay, установив для BTAsset параметр BT_Muffin:

Теперь BT_Muffin будет запускаться каждый раз, когда появляется AIC_Controller.

Для сохранения результатов нажмите Compile и вернитесь в главный редактор. Нажмите Play и посмотрите, как теперь себя ведут маффины, которых вы создаете:

Настройка функции (Perception) восприятия ИИ

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

Откройте AIC_Muffin и добавьте новый компонент AIPerception:

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

Для этого нужно выбрать AIPerception и перейти к панели Details. В меню AI Perception добавьте новый элемент для Senses Config:

Добавьте еще один элемент 0 в настройках AI Sight, и разверните его свойства:

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

  • Sight Radius: тут указывается максимальное расстояние, на которое может видеть объект. Сделайте его равным 3000.
  • Lose Sight Radius: Это расстояние, на которое должен отойти враг, прежде, чем персонаж потеряет его из виду. Установите его равным 3500.
  • Peripheral Vision Half Angle Degrees: Тут устанавливается угол обзора для персонажа, другими словами это периферийное зрение. Вам нужно указать значение 45, чтобы угол обзора был равен 90.

Сейчас AI Perception обнаруживает только врагов (объекты, которые назначены в другую группу). Однако игровые персонажи по умолчанию относятся к нейтральным объектам.

На момент написания статьи не существует способа назначать команды, используя Blueprints. Вместо этого вы должны настроить AI Perpcetion на обнаружение нейтральных объектов. Для этого разверните меню Detection by Affiliation и включите Detect Neutrals:

Нажмите Compile, чтобы сохранить результаты и затем вернитесь в главный редактор. Нажмите Play и создайте несколько кексов. Нажмите на клавиатуре , чтобы отобразить экран отладки ИИ. Нажмите 4 на цифровой клавиатуре, чтобы визуализировать восприятие ИИ. Когда маффин перемещается, то появляется зеленая область, обозначающая его зрение:

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

Создание ключа для обозначения врагов

Откройте BB_Muffin и добавьте ключ типа Object. Измените название ключа на Enemy:

Прямо сейчас вы не сможете использовать Enemy в MoveTo, потому что этот ключ является объектом, а не вектором.

Чтобы это исправить, выберите Enemy и развернув меню Key Type измените Base Class на Actor. Это позволит дереву поведения распознавать врага в игровом персонаже:

Закройте BB_Muffin.

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

Настройка движения в сторону врагов

Откройте BT_Muffin и отключите параметр Sequence and Root. Вы можете сделать это, щелкнув правой кнопкой мыши по линии соединения и выбрав соответствующую команду.

Посмотрите на изображение и создайте в той же последовательности выделенные узлы, указав для их Blackboard Key значение Enemy:

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

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

Использование ключей для обозначения врагов

Откройте AIC_Muffin, выберите компонент AIPerception и добавьте новое событие «On Perception Updated»:

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

Добавьте выделенные на изображении узлы и убедитесь в том, что вы установили для Make Literal Name значение Enemy:

Таким образом будет выполняться проверка, есть ли в локации противник ИИ, а если враг отсутствует, то вам нужно его добавить. Для этого установите выделенные на изображении узлы:

Резюмируя:

  1. IsValid проверяет, установлен ли ключ Enemy;
  2. Если он не установлен, вам нужно пересмотреть всех активных на данный момент персонажей в игре;
  3. Cast To BP_Muffin проверяет, является ли объект маффином;
  4. Если это действительно маффин, необходимо проверить жив ли он;
  5. Если IsDead = false, то необходимо назначить новый маффин в качестве врага и разорвать цикл.

Нажмите Compile, закройте AIC_Muffin и нажмите Play, чтобы проверить поведение ваших маффинов. Создайте двух персонажей, чтобы они находились напротив друг друга, при этом один из них должен будет начать движение к другому:

Объединение действий

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

Откройте BT_Muffin и создайте новый узел Selector, подключив его следующим образом:

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

  • Attack: Если все задачи выполнены успешно, последовательность также будет выполнена. При этом Selector остановит выполнение последовательности после завершения действий.
  • Roam: Если Enemy не выявлен, MoveTo не сможет быть выполнено, соответственно последовательность прервется. Selector запустит выполнение следующего блока действий, которые предусмотрены в этом случае.

Вернитесь в главный редактор и нажмите Play. Создайте несколько кексов, чтобы проверить в действии внесенные изменения:

Возникает вопрос – почему маффин не нападает сразу?

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

Создание узла Decorator

Как и любой сервис, decorator должен быть прикреплен к задачам или композитам. Как правило, этот тип узлов используется для выполнения различных проверок. Если результат равен true, decorator также вернет true и наоборот. Кроме того, узлы типа decorator имеют возможность прервать последовательность дерева поведения в любом месте. Таким образом становится возможность настройки атаки маффина сразу после обнаружения врага.

Для этого вам нужно открыть BT_Muffin и щелкнуть правой кнопкой мыши по последовательности Sequence. Теперь выполните Add Decorator Blackboard, чтобы соединить Blackboard с Sequence:

Затем выберите декоратор Blackboard и перейдя к панели Details, установите значение Enemy для Blackboard Key:

Использование функции Observer Aborts

Чтобы настроить прерывание последовательности в определенном месте можно использовать два способа:

  1. Self: этот параметр позволяет блоку атаки прерываться, когда враг пропадает или умирает.
  2. Lower Priority: этот параметр приведет к тому, что блоки с более низким приоритетом будут отменены, когда установлен Enemy.

Установите значение Observer Aborts на Both, чтобы можно было использовать оба типа прерывания:

Сравните с изображением – именно так сейчас должно выглядеть ваше дерево поведения:

Резюмируя настройку ветки атаки:

  1. Selector будет запускать ветку атаки, если выявлен враг;
  2. Игровой персонаж будет сам двигаться в направлении врага;
  3. После этого он выполнит действие атаки;
  4. Далее персонаж будет находиться в режиме ожидания две секунды.

Резюмируя настройку ветки перемещения:

  1. Selector будет запускать ветку перемещения, если атака потерпит неудачу;
  2. BTService_SetRandomLocation сгенерирует случайное местоположение;
  3. Персонаж переместится в сгенерированную точку;
  4. После этого он будет находиться в режиме ожидания пять секунд;

Закройте BT_Muffin и нажав Play, создайте несколько кексов. Наслаждайтесь битвой кексов и результатом своей работы:

Что делать дальше?

Вы можете скачать готовый проект.

Теперь вы можете самостоятельно настроить дерево поведения для персонажа, использовав возможности ИИ.

Если вы хотите использовать более продвинутый ИИ, изучите страницу документации Environment Query System. Эта система позволит вашему ИИ собирать данные о среде и реагировать на нее.

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

Перевод
raywenderlich.com
Показать еще

5 Comments

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

  2. я один не понял как подключить BTTask_Attack. если я пытаюсь его сделать, у меня ничего не получается. Помогите

      1. В стартовом проект действительно нет BTTask_Attack и его создание не раскрывается в тексте урока. По-хорошему стоило бы его добавить в стартовый проект или описать процесс создания.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Back to top button