Вражеские персонажи
В Unreal Engine неигровые персонажи и противники в целом устроены так же, как и игрок: для них также предусмотрены контроллер и пешка. В целом, как противники, так и игрок имеют общий функционал благодаря общему базовому классу AParrotCharacterBase. В игре Parrot поведение врагов управляется с помощью деревьев поведения, а их контроллеры создаются на основе класса контроллера ИИ. Начнём с анимационной схемы Blueprint, так как она используется всеми вражескими персонажами.
Анимационные схемы Blueprint врагов
Шаблоны анимационных схем Blueprint
Для случаев, когда у вас несколько скелетных сеток, которые будут анимироваться одинаково, вы можете создать шаблоны анимационных схем Blueprint (см. раздел Animation Blueprint Linking (Связывание анимационных схем Blueprint)). В игре будет четыре типа врагов: безголовый скелет, обычный скелет, обычная акула и акула-босс. Поскольку все они имеют одинаковый скелет и конфигурацию анимации, можно создать единый шаблон, реализующий граф анимации и граф событий. Посмотреть, как устроен этот шаблон, вы можете здесь: Blueprints > Enemy > EnemyBase > ABT_EnemyBase. Он очень похож на анимационную схему Blueprint игрока, так как шаблон настраивается почти так же, как и сама анимационная Blueprint-схема.
Анимационные схемы Blueprint
В этом случае вся реализация будет выполнена в шаблоне без анимаций как таковых, поскольку шаблон не привязан к конкретному скелету. Каждый противник будет иметь свою анимационную схему Blueprint на основе шаблона, а в графе анимации через переопределения будут добавлены анимации соответствующего скелета. Ознакомиться с примером вы можете здесь: Blueprints > Enemy > HeadlessSkeleton > ABP_Enemy_HeadlessSkeleton.
Ниже мы выбрали подходящие анимации для скелетной сетки безголового скелета для каждого состояния анимации.
Пешка противника
Вражеские персонажи в игре Parrot во многом схожи с игроком, особенно по очкам здоровья и другим похожим функциям (например, смерти). Общую реализацию можно найти в AParrotCharacterBase. Для реализации, характерной для врагов, используется подкласс AParrotEnemyCharacterBase. Он отвечает за всю реализацию работы системы патрулирования, боевой системы и других функций. О том, как устроена боевая система, см. в статье Боевая система в игре Parrot.
С такой конфигурацией проверка ударов и нанесённого урона производится на враге, а реализация того, как будут активироваться области, находится в базовом классе схемы Blueprint, который можно найти здесь: Blueprints > Enemy > EnemyBase > BP_EnemyCharacter_Base.
Эта реализация выполняется здесь, а не в исходном классе C++, поскольку области активации должны быть разными для каждого из противников из-за различий в их формах, размерах и сложности их сеток. Это необходимо, поскольку наследуемую область активации нельзя изменить в производном классе.
Контроллер ИИ противника
Как уже упоминалось ранее, противники управляются с помощью деревьев поведения, поэтому в AParrotEnemyAIControllerBase имеется базовый класс, наследуемый от AIController. Здесь вы найдёте различные события BlueprintImplementableEvents, используемые для перенаправления данных в информационную доску для дальнейшего использования деревьями поведения.
С тем, как контроллер ИИ передаёт данные дереву поведения и как он обрабатывает обнаружение присутствия игрока, вы можете ознакомиться здесь: Blueprints > AI > EnemyBase > BP_EnemyController_Base.
Использование деревьев поведения для создания ИИ
Unreal Engine предлагает мощную и гибкую инфраструктуру для создания ИИ с использованием деревьев поведения. Краткое руководство по настройке базового шаблона с реализацией некоторых видов поведения можно найти в разделе Behavior Tree Quick Start Guide. Результаты из этого руководства используются в качестве основы для ИИ врагов и дорабатываются в соответствии с необходимым поведением.
Для создания базовой системы патрулирования и нападения на игрока существуют две задачи дерева поведения: Blueprints > AI > EnemyBase > BTT_FindNextPatrol и Blueprints > AI > EnemyBase > BTT_AttackPlayer. Все противники используют общую информационную доску (Blueprints > AI > EnemyBase > BB_Enemy_Base), поскольку инфраструктура, необходимая для поддержки всех функций, уже присутствует у каждого из них. То, какие функции использовать для настройки поведения противников, будет зависеть непосредственно от реализации дерева поведения.
У каждого из противников будет своя конфигурация дерева поведения, поэтому каждый из них будет вести себя по-своему. Ознакомиться со всеми четырьмя из них вы можете здесь:
Blueprints> AI > HeadlessSkeleton > BT_HeadlessSkeleton;
Blueprints > AI/Skeleton > BT_Skeleton;
Blueprints > AI > Sharky > BT_Sharky;
Blueprints > AI > BossShark > BT_Boss_Shark.
Создание настраиваемой системы точек патрулирования
Для противников в игре Parrot не требуется система патрулирования из руководства по дереву поведения, где ИИ противника случайным образом каждые 4 секунды выбирает точку в пределах заданного радиуса, к которой он будет двигаться. Вместо этого нужно, чтобы противники чётко следовали по заданному маршруту в обоих направлениях — как это реализовано во многих платформерах.
Для этого в игре Parrot была создана собственная система, которая обеспечивает все необходимые возможности. Она включает компонент UParrotEnemyPatrolRigComponent, который можно разместить в сцене для управления патрулированием. Для создания экземпляра сплайна здесь используются подобъекты класса по умолчанию. Сплайн используется для создания точек патрулирования, двух областей активации (используемых для запуска поведения ИИ) и визуализатора, работающего только в редакторе, который будет отображать порядок точек маршрута. Упорядочивание точек маршрута позволяет наглядно отобразить направление маршрута патрулирования в процессе редактирования. Более подробно с этим можно ознакомиться в реализации на C++ в UParrotEnemyPatrolRigComponent.
Эта реализация представляет собой компонент, позволяющий прикрепить каркас патрулирования к любому актору в сцене. Это позволяет разместить каркас на движущемся объекте и означает, что патруль будет сохранять правильное расположение в локальном пространстве. Для размещения каркаса патрулирования, не прикреплённого к уже имеющемуся актору в сцене, существует AParrotEnemyPatrolRigActor — актор, который можно разместить в любом месте в сцене и который создаёт на себе UParrotEnemyPatrolRigComponent как подобъект по умолчанию.
Эта реализация позволяет выбрать противника, которого мы создадим в среде выполнения для следования по маршруту патрулирования. Этот процесс использует функцию Unreal Engine, называемую отложенным созданием актора, которая позволяет создавать актора в два этапа: на первом создаётся объект актора без выполнения инициализации AActor, например, BeginPlay. Это позволяет добиться достаточной гибкости настроек, необходимых для актора перед его инициализацией. После выполнения этих шагов вызывается второй этап для завершения создания и инициализации актора. Это выполняется для каркаса патрулирования, чтобы при создании актора противника сплайн патрулирования и области активации можно было передать актору для последующей обработки при его инициализации и автоматического запуска последовательности патрулирования.
С кодом, выполняющим отложенное создание актора, вы можете ознакомиться в UParrotEnemyPatrolRigComponent. Аналогичная возможность предусмотрена и в схемах Blueprint, где вы можете добавить тег Expose on Spawn (Раскрыть при создании) в свойства актора схемы, что позволит передавать аргументы, которые задаются до инициализации актора, в узел схемы создания.
На изображении ниже представлен пример настройки каркаса патрулирования в папке Maps > Level_1 > Level_1: здесь каркас патрулирования состоит из двух точек, начиная с точки 0 справа. Каркас патрулирования настроен таким образом, чтобы создавать BP_EnemyCharacter_Skeleton.
Ниже представлено меню переключения Общее отображение, благодаря которому можно определить точки маршрута каркаса патрулирования для удобства при редактировании. Большинство галочек в меню установлены. Подробнее о том, как это реализовано в компоненте визуализатора (только для редактора), можно узнать здесь: UParrotPatrolRigDebugVisualizer.