Unreal Engine 4. Учебник для начинающих, часть 10: Как создать простой шутер
В этом уроке по Unreal Engine 4 вы узнаете, как самостоятельно создать простой шутер от первого лица. Вы научитесь создавать персонажа, который будет стрелять по врагам из оружия.
Шутер от первого лица (FPS) — это жанр, в котором игрок использует оружие и перемещается по игровой локации с видом от первого лица. Игры FPS очень популярны у геймеров, о чем свидетельствуют такие проекты, как Call of Duty и Battlefield.
Кстати говоря, изначально Unreal Engine создавался именно для создания игр FPS.
В этом уроке вы узнаете, как:
- Создать персонажа с управлением от первого лица, который сможет перемещаться по карте и осматриваться вокруг;
- Создать объект в виде пистолета и поместить его в руки игрового персонажа;
- Стрелять из оружия, используя линию трассировки;
- Наносить урон врагам.
Это занятие является частью серии, которая состоит из 10 уроков, посвященных Unreal Engine:
Начало работы
В первую очередь вам необходимо скачать стартовый проект и все материалы, необходимые для работы. Разархивируйте файл и откройте BlockBreaker.uproject.
Перед вами появится следующая локация:
Посмотрите, зеленая стена состоит из нескольких блоков. Вам нужно сделать так, чтобы во время получения урона каждый блок становился красного цвета, а когда его здоровье достигнет нулевого значения, то он исчез. Красная кнопка на полу должна перезапускать цели.
Для начала вам нужно создать игрового персонажа.
Создание игрового персонажа
Перейдите в папку Blueprints и создайте новый Blueprint Class. Выберите Character в качестве основного класса и назовите его BP_Player:
Character — это один из типов игровых объектов, но с дополнительными функциями, например, такими как компонент CharacterMovement:
Этот компонент автоматически обрабатывает движения персонажа, такие как ходьба и прыжки. Вам просто нужно использовать для этого соответствующую и установить данные переменных, таких как скорость перемещения.
Прежде чем вы сможете сделать какие-либо действия игровым персонажем, необходимо указать момент нажатия клавиши движения. Для этого используются настройки клавиш W, A, S и D.
Примечание: Если вы не знаете, как это сделать, рекомендуем прочитать предыдущие уроки, особенно раздел, посвященный изучению Blueprints.
Настройка движения персонажа
Вам нужно выполнить Edit ⇒ Project Settings и открыть раздел Input. Теперь создайте два объекта Axis Mappings и назовите их MoveForward и MoveRight соответственно. MoveForward будет использоваться для движения игрока вперед и назад, а MoveRight влево и вправо:
Нужно назначить для MoveForward в качестве ключа значение измените W. Теперь тут же создайте еще один ключ со значением S и впишите в поле Scale число -1.0:
Примечание: Если вы хотите больше узнать о поле «Scale», обратитесь к руководству по Blueprints. Главы Axis Value и Input Scale описывают, что это такое и как его использовать.
Немного позже вам нужно будет умножить значение масштаба на значение координат персонажа. Это даст вам данные, который будут использоваться для движения вперед, если результат положительный. Если же он имеет отрицательное значение, то эти данные будут использоваться для движения назад.
Сделайте тоже самое для настройки перемещения влево и вправо, добавив D ключ для MoveRight. После этого создайте новый ключ A = -1.0:
Реализация передвижения персонажа
Откройте BP_Player и Event Graph, чтобы добавить новое событие MoveForward, которое будет выполняться каждый кадр, даже если вы ничего не нажимаете.
Это событие также будет выводить значение оси, относительно значения шкалы, которое вы установили ранее. При нажатии W это значение будет равно 1, а при нажатии S — 1. При условии, что ни одна из этих клавиш не задействована, будет использоваться значение 0.
Сейчас вам нужно настроить команду движения для персонажа, создав узел Add Move Input и подключив его следующим образом:
Чтобы определить значение Add Move Input нужно взять вектор и умножить его на значение масштаба. Таким образом получится нужное направление, в соответствии с которым компонент CharacterMovement будет перемещать персонажа.
Укажем в каком направлении должен двигаться игровой персонаж при помощи нового вектора Get Actor Forward Vector, который вам следует создать и подключить следующим образом:
Резюмируя:
- MoveForward запускает каждый кадр и выводит значение оси. Это значение будет равно 1, если вы нажмете W и -1, если вы нажмете S. Если вы не нажмете ни одну из клавиш, это значение будет равно 0.
- Узел Add Move Input вводит вектор направления движения персонажа со значением масштаба. Таким образом устанавливается команда движения вперед или назад.
- Компонент CharacterMovement получает результат из Add Movement Input и перемещает персонаж в этом направлении, либо персонаж будет стоять на месте, если не используется ни одна из команд.
Теперь вам нужно повторить процесс для MoveRight, но при этом заменить Get Actor Forward Vector на Get Actor Right Vector:
Установка расположения персонажа по умолчанию
Нажмите Compile, чтобы сохранить результаты и вернитесь в главный редактор. Вам нужно открыть панель World Settings и найдя тут раздел Game Mode, и заменить Default Pawn Class на BP_Player:
Примечание: Если у вас нет панели World Settings, перейдите к панели Toolbar инструментов и выберите Settings ⇒ World Settings.
Теперь вы будете автоматически использовать BP_Player при запуске игры. Нажмите Play и используйте клавиши W, A, S и D для перемещения, чтобы протестировать внесенные изменения:
Сейчас вам не хватает еще нескольких команд, чтобы персонаж мог осматриваться вокруг себя, для этого вы будете использовать Look Mappings.
Создание Look Mappings
Откройте Project Settings и создайте два новых Axis Mappings с названиями LookHor Horizontal и LookVertical:
Установите ключ для LookHor horizontal на значение Mouse X:
Это отображение выведет положительное значение при перемещении мыши вправо и наоборот.
Затем измените ключ для LookVertical на значение Mouse Y:
Это отображение выведет положительное значение при перемещении мыши вверх и наоборот.
Теперь вам нужно создать логику для осмотра вокруг себя.
Внедрение функции осмотра вокруг себя
Если у игрового персонажа все еще нет компонента Camera, Unreal создаст его автоматически. По умолчанию эта камера будет зависеть от используемого контроллера.
Примечание: Больше информации о возможностях контроллера вы можете получить из урока, посвященному работе с ИИ.
Несмотря на то, что контроллеры не являются физическими объектами, они имеют свои настраиваемые функции. Таким образом вы можете настроить вид персонажа и камеры в зависимости от того, какие цели вы преследуете – создаете игру от первого, где камера смотрит в одном направлении с персонажем, или от третьего лица, где камера и персонаж могут смотреть в разные стороны:
Чтобы повернуть камеру в игре от первого лица, все, что вам нужно сделать, это изменить вращение контроллера. Для этого откройте BP_Player и создайте новое событие LookHorizont:
Чтобы камера могла поворачиваться вслед за персонажем в разные стороны, нужно отрегулировать поворот контроллера. Для этого создайте выход Yaw Add Controller и подключите его следующим образом:
Теперь, при движении мышки по горизонтали, персонаж будет поворачивать свой взгляд (обзор) влево или вправо.
Повторите процесс для LookVertical, но замените Add Controller Yaw Input на Add Controller Pitch Input:
Если вы запустите сейчас игру, то заметите, что вертикальный обзор работает не совсем корректно — при движении мыши вверх, камера смотрит вниз и наоборот.
Чтобы это исправить, умножьте значение оси на -1 для инвертирования обзора:
Нажмите Compile, чтобы сохранить результат, а затем нажмите Play и посмотрите изменения в действии:
Создание оружия
Из предыдущих уроков вы должны помнить, что при помощи инструмента Blueprint вы можете выбрать готовый или создать новый проект с индивидуальными настройками каждого объекта. Эта функция очень полезна, когда у вас есть разные типы объектов, которые имеют общие функции.
Допустим, вам нужно сделать несколько видов автомобилей. Вы можете создать базовый класс автомобиля, который содержит переменные, такие как скорость и цвет. Затем вы можете установить классы (дочерние элементы), которые используют базовый тип автомобиля в качестве основного. Каждое ответвление также будет содержать одинаковые переменные. Таким образом вы получите одинаковые автомобили с различными значениями скорости и разными цветами, приложив минимум усилий для их создания.
Вы можете использовать тот же метод для создания оружия. Для этого вам нужно сначала создать базовый класс.
Создание базового класса для оружия
Вернитесь в главный редактор и создайте Blueprint Class установив его тип на Actor. Назовите новый класс BP_BaseGun и откройте его.
Теперь вам нужно создать несколько типа float переменных, которые будут определять некоторые свойства оружия:
- MaxBulletDistance: на какое расстояние будет перемещаться каждая пуля;
- Damage: какой урон от выстрела получит цель;
- FireRate: сколько времени должно пройти между выстрелами (в секундах).
Примечание: для каждой переменной установлено значение по умолчанию — ноль, что вполне подходит для этого урока. Однако, если вы хотите, чтобы новые классы оружия имели другие значения, то вы должны установить их в BP_BaseGun.
Теперь вам нужно создать физическое представление о пистолете. Добавьте компонент Static Mesh и назовите его GunMesh:
Создание дополнительных классов оружия
Нажмите Compile для сохранения результата работы и вернитесь в главный редактор. Чтобы создать дополнительный класс, щелкните правой кнопкой мыши BP_BaseGun и выберите команду Create Child Blueprint Class:
Назовите новый объект BP_Rifle и откройте его. Вам нужно установить для каждой переменной следующие значения:
- MaxBulletDistance: 5000
- Damage: 2
- FireRate: 0,1
Теперь каждая пуля будет преодолевать максимальное расстояние равное 5000. Если она попадет в какой-либо объект, то нанесет 2 единицы повреждения. При выполнении последовательных выстрелов продолжительность каждого из них будет составлять не менее 0,1 секунды.
Далее вам необходимо указать, какая физическая сетка должна использоваться для пистолета. Выберите компонент GunMesh и установите для его Static Mesh значение SM_Rifle:
Нажмите Compile, закройте BP_Rifle и ваш пистолет будет готов, осталось только установить для него компонент камеры.
Создание камеры
Откройте BP_Player и создайте новый компонент Camera с названием FpsCamera:
Сейчас положение камеры по умолчанию находится слишком низко, поэтому может сложиться впечатление, что вы управляете карликом или ребенком. Установите местоположение FpsCamera в положение (0, 0, 90):
Кроме того, сейчас компонент камеры зависит от перемещения контроллера. Чтобы это исправить, перейдите на панель Details и включите Camera Settings ⇒ Use Pawn Control Rotation:
Далее вам нужно указать, где должно находиться оружие.
Определение местоположения оружия
Чтобы указать местоположение оружия, можно использовать компонент Scene, который идеально подходит для этой цели, потому что содержит только значение Transform. Убедитесь, что у вас выбран FpsCamera, создайте компонент Scene, и назовите его GunLocation:
Теперь пистолет будет всегда находиться перед камерой, создавая иллюзию того, что он в руках игрока.
Установите местоположение GunLocation на (30, 14, -12), чтобы он находился немного в стороне от камеры:
После этого установите для параметра rotation координаты (0, 0, -95):
Теперь необходимо создать само оружие и связать его с GunLocation.
Прикрепление оружия с помощью Spawning
Найдите событие BeginPlay и создав Spawn Actor From Class, установите его значение Class на BP_Rifle:
Теперь создайте переменную типа BP_BaseGun и назовите ее EquippedGun.
Примечание: очень важно, чтобы переменная не имела тип BP_Rifle, потому что игроку в дальнейшем будет необходимо использовать различные типы оружия, а не только винтовку. Если вы создадите оружие другого типа, вы не сможете сохранить его в переменной типа BP_Rifle. Используя переменную типа BP_BaseGun, вы создаете пространство, которое может принимать множество разных объектов.
Затем соедините EquippedGun с выходом Return Value узла Spawn Actor From Class:
Чтобы прикрепить пистолет, вам необходимо использовать AttachToComponent. Создайте этот узел и установите для Location Rule и Rotation Rule значение Snap to Target:
Далее создайте ссылку на GunLocation и соедините следующим образом:
Резюмируя:
- Когда появляется BP_Player, создается экземпляр BP_Rifle;
- EquippedGun сохраняет ссылку на BP_Rifle для его дальнейшего использования;
- AttachToComponent прикрепляет пистолет к GunLocation.
Чтобы сохранить результат, нажмите Compile и попробуйте нажать Play, чтобы посмотреть на ваше новое оружие в игре:
Теперь самое интересное: стрельба из оружия! Чтобы проверить, попала ли пуля в цель, вы можете использовать трассировку.
Стрельба из оружия
Трассировка — это функция, которая задает начальную и конечную точки (которые образуют линию) на условном отрезке пространства. Объект должен пересечь каждую точку вдоль линии (от начала до конца), пока не достигнет определенной цели.
Поскольку стрельба относится к функции оружия, она должна идти в класс оружия, а не в игрока. Откройте BP_BaseGun и создайте функцию под названием Shoot. Затем создайте два вектора и назовите их StartLocation и EndLocation. Это будут начальная и конечная точки линии стрельбы:
Вы также можете выполнить трассировку линии, используя узел LineTraceByChannel. Создайте его и подключите следующим образом:
Затем вам нужно проверить, не попала ли линия трассировки. Создайте узел Branch и подключите его как показано на изображении:
Выход Return Value будет иметь значение true, если пуля попала в цель и наоборот.
Чтобы визуально было видно эффект стрельбы, можно использовать эффекты, созданные с помощью частиц.
Частицы для создания эффекта попадания пули
Переместите Out Hit на график и в появившемся меню выберите Break Hit Result:
Таким образом вы получите новый узел с разными выходами, предназначенными для настройки трассировки полета пули.
Создайте Spawn Emitter в Location и установите для Emitter Template значение PS_BulletImpact. После этого подключите его выход Location к такому же выходу Break Hit Result:
Посмотрите, как должен выглядеть общий график:
Резюмируя:
- Shoot отвечает за трассировку лини полета пули;
- В случае попадания в цель, Spawn Emitter at Location вызывает PS_BulletImpact;
Использование функции стрельбы
Во-первых, вам нужно создать раскладку клавиш клавиатуры для стрельбы. Нажмите Compile, откройте Project Settings и создайте новое событие Axis Mapping под названием Shoot. Установите его ключ на левую кнопку мыши, а затем закройте окно Project Settings:
После этого откройте BP_Player и создайте новое событие Shoot:
Чтобы проверить, нажимает ли игрок клавишу Shoot, вам просто нужно проверить, равно ли значение Axis значению 1. Теперь создайте и разместите выделенные на изображении узлы:
Создайте ссылку на EquippedGun и назовите ее Shoot function:
Расчет местоположения трассировки линии полета пули
Во многих FPS играх пули начинают свое движение от камеры, а не от пистолета. Чтобы сделать так же, создайте ссылку на FpsCamera и подключите ее к GetWorldLocation:
Теперь вам нужно указать конечное местоположение. Помните, что у оружия есть переменная MaxBulletDistance, в которой используются единицы для указания местоположения. Вам нужно создать выделенные на изображении узлы:
Подключите все следующим образом:
Резюмируя:
- Когда игрок нажимает или удерживает нажатой левую кнопку, пистолет выстреливает пулями, которые вылетают от места расположения камеры;
- Пуля будет двигаться на расстояние, указанное в MaxBulletDistance.
Нажмите Compile, чтобы сохранить результаты, а затем нажмите Play и попробуйте выстрелить из оружия:
В настоящее время пистолет стреляет пулями каждый кадр, таким образом процесс происходит слишком быстро, поэтому следующим шагом вам будет нужно снизить скорострельность оружия.
Уменьшение скорострельности
Во-первых, вам нужна переменная, чтобы решить, может ли игрок стрелять. Откройте BP_Player и создайте логическую переменную с именем CanShoot. Установите ее значение по умолчанию в true и измените Branch следующим образом:
Теперь выстрел будет происходить, только если нажата клавиша Shoot и CanShoot равен true. Добавьте выделенные на изображении узлы:
Что поменялось:
- Игрок стреляет только когда удерживает левую кнопку и CanShoot равен true;
- Как только игрок совершает выстрел, CanShoot становится равен false;
- CanShoot меняет значение на true, после времени, которое устанавливается FireRate;
Чтобы сохранить результаты нажмите Compile и закройте BP_Player. Нажмите Play и проверьте текущую скорострельность оружия:
Нанесение урона
В Unreal каждый объект имеет возможность получать настраиваемый урон. Например, при получении урона персонаж файтинга теряет здоровье, а тот же воздушный шар лопается, вместо этого.
Откройте BP_BaseGun и добавьте Apply Damage в конце функции Shoot:
Теперь нужно указать, какому объекту будет наносится урон. Для этого соедините Damaged Actor с Hit Actor узла Break Hit Result:
Чтобы указать количество нанесенного урона вам нужно получить ссылку на Damage и подключить его к Base Damage:
Теперь Shoot наносит повреждения всем объектам, которые попадают под линию стрельбы. Нажмите Compile и закройте BP_BaseGun.
Получение урона
Откройте BP_Target и создайте новое событие AnyDamage, которое будет выполняться всякий раз, когда объект получает урон:
После этого вам нужно подключить контакты функции TakeDamage следующим образом:
Теперь, когда цель будет получает урон, она потеряет здоровье. Нажмите Compile, а затем закройте BP_Target.
Далее откройте BP_ResetButton, создайте событие AnyDamage и откройте функцию ResetTargets:
Таким образом произойдет перезагрузка целей, если выстрелить по красной кнопке. Нажмите Compile и закройте BP_ResetButton.
Нажмите Play, чтобы проверить как работают новые функции:
Что делать дальше?
Вы можете скачать готовый проект.
Несмотря на то, что игра, которую вы сейчас создали, очень простая, ее можно улучшить, добавив новые функции и возможности, используя знания, которые вы получили из предыдущих уроков.
Это была последняя часть учебных пособий по Unreal Engine для начинающих. В ближайшее время мы планируем создать еще много уроков для более глубокого изучения возможностей этого движка.
Странно, что нет комментариев.
Спасибо большое!
Присоединяюсь к комментатору выше — крайне познавательный курс. Большое спасибо за проделанную работу!