Весь цикл статей

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

Для начала нам нужно создать несколько С++ классов - CharacterPlayer Controller и GameMode.

В Content Browser перейдем в папку "С++ Classes"

Если этой папки нет, то ее отображение можно включить нажав на View Options и поставить галочку на Show C++ Classes.

Перейдя в папку с С++ классами, щелкаем ПКМ в окне Content Browser и выбираем New C++ Classes

Появится окно с классами от которых мы можем наследоваться.

Создадим класс для нашего персонажа, поэтому в качестве родительского класса выбираем Character и щелкаем Next

В следующем окне нужно указать имя класса и его расположение. Для всех классов в проекте мы будем делать приписку SH(Survival Horror)

Также нажмем на Public, чтобы заголовочные файлы(*.h) находились в папке Public, а *.cpp файлы в папке Private.

В пути файла допишу Player. Таким образом создастся папка с аналогичным названием и туда поместится наш класс. Потом нажимаем Create Class.

После компиляции в редакторе кода можно увидеть созданные файлы

Аналогичным образом создадим Player Controller с именем SHPlayerController и также поместим его в папку Player

И создадим последний класс GameModeBase с именем SHGameModeBase

Он будет лежать просто в папке Public и Private

В папке Content создадим новую папку и назовем ее Blueprints. И уже внутри нее создадим папку Player.

Теперь из наших C++ классов нужно сделать Blueprint классы.

Переходим в папку с С++ классами персонажа и щелкаем ПКМ по классу SHCharacter, в появившемся меню выбираем Create Blueprint class based on SHCharacter.

Появится окно. Здесь указываем имя класса. Blueprint классы принято начинать с префикса BP_. Также нужно указать папку, где необходимо его создать, в нашем случае Player. Нажимаем Create Blueprint Class.

Как именовать файлы в Unreal Engine можно узнать из этого репозитория на GitHub - https://github.com/ShadowPKx/ue4-style-guide-rus

Откроется окно с редактором Blueprint класса, его пока можно закрыть. Сначала создадим еще два класса.

Аналогично создаем класс для Player Controller.

И для нашего SHGameModeBase, только расположение выбираем просто папку Blueprints.

Теперь перейдем в BP_GameModeBase

Здесь в Player Controller Class необходимо выбрать наш Player Controller

И тоже самое проделать с Default Pawn Class

Дальше перейдем в настройки проекта Edit->Project Settings. Дальше в категорию Maps&Modes. И в Default GameMode выберем наш класс.

Теперь откроем Blueprint класс BP_SHCharacter и установим для него Skeletal Mesh манекена.

В компонентах находим Mesh

После этого в Details ищем Skeletal Mesh и выбираем для него необходимый Mesh

Перейдем во Viewport и увидим, что Mesh нужно опустить и повернуть

По оси Z опускаем его на -88 и поворачиваем на -90 градусов

Теперь он подходит под компонент капсулы и смотрит в нужную сторону, об этом нам "говорит" компонент стрелка.

Теперь приступим к написанию кода для управления персонажем и камерой.

Сначала перейдем в Edit->Project Settings. Потом в категорию Input. Здесь нам нужно назначить mappings, т.е. клавиши, мышь, кнопки геймпада и т.д., которые будут отвечать за какое-либо действие в игре.

Есть два типа mapping Action и Axis.

Action - подходят для каких то разовый действий, например, нажать на кнопку действия и начать разговоров с НПС.

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

В данный момент нам нужен Axis.

Если его сейчас развернуть, то там уже есть созданные mappings. Потому что мы добавляли шаблон от третьего лица. Удалим их, нажав на крестик напротив каждого из них. Тоже самое можно сразу проделать с Action.

Теперь создадим новый нажав на "+" и дадим ему имя MoveForward. Он будет отвечать за движение вперед и назад

Напротив него нажмем на "+", чтобы создать еще одно поле для клавиши

Теперь щелкаем по первому полю None и через поиск ищем клавишу W, он будет отвечать за движение вперед. Scale оставляем равным 1.

Для второго поля выбираем клавишу S, а Scale изменяем на -1.

Этот Scale будет принимать значение от -1 до 1, в зависимости от нажатой клавиши.

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

Третий mapping с именем LookUp будет отвечать за управление камерой по вертикали. Scale ставим -1, чтобы не было инверсии.

И последний mapping с именем Turn отвечает за управление камерой по горизонтали

Теперь переходим в редактор кода. Нам понадобится открыть наш класс SHCharacter.h и SHCharacter.cpp.

Сначала создадим два компонента - CameraComponent и SpringArmComponet. Т.е. камера будет висеть на этом компоненте и как бы летать по орбите вокруг персонажа.

Чтобы создать новые компоненты, для начала в заголовочном файле SHCharacter.h в секции protected объявим два указателя на UCameraComponent и USpringArmComponent c именами CameraComponent и SpringArmComponent.

Для каждого указателя используем макрос UPROPERTY со следующими спецификаторами (VisibleAnywhere, BlueprintReadWritem, Category = "Components").

Про них подробнее можно почитать в офф документации по ссылке - https://docs.unrealengine.com/4.26/en-US/ProgrammingAndScripting/GameplayArchitecture/Properties/Specifiers/

Сейчас указатели подсвечиваются красным(указывает на ошибку). Связано с тем, что не подключены заголовочные файлы для этих компонентов. Заголовочные файлы мы будем подключать в SHCharacter.cpp.

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

Для этого после всех include и перед макросом UCLASS() необходимо добавить следующие строки.

Теперь переходим в SHCharacter.cpp. В данный момент мы только объявили указатели для этих компонентов, но еще их не создали.

Сначала мы подключим заголовочные файлы для них.

Теперь в конструкторе класса будем их создавать.

Чтобы создать новый компонент необходимо воспользоваться шаблонной функцией CreateDefaultSuboject. Т.е. мы указываем какой класс действительно хотим создать(USpringArmComponent), а в качестве входного параметра передаем строку с именем компонента.

Теперь вызовем функцию SetupAttachment у SpringArmComponent, чтобы присоединить его к корневому компоненту(RootComponent).

Функция GetRootComponent как раз возвращает указатель на корневой компонент.

Также у SpringArmComponent есть параметр bUsePawnControlRotation, его мы изменим на true, чтобы этот компонент использовал вращение контролера и мы могли поворачивать персонажа с помощью мыши.

Аналогичным образом создаем компонент камеры.

Но теперь присоединяем ее к нашему SpringArmComponent

Полностью код в конструкторе выглядит следующим образом

Теперь скомпилируем проект и перейдем в BP_SHCharacter.

У нас появились два наших компонента

И также видим камеру, которая висит на краю SpringArmComponent

Выберем SpringArmComponent и изменим его положение. Я выставлю следующие

Камера у меня висит как бы из-за плеча

Возвращаемся в редактор кода в файл SHCharacter.h

Создаем приватную секцию. В ней объявим две функции MoveForward и MoveRight с одним параметром типа float. В этих функциях будет логика перемещения персонажа.

Теперь перейдем в SHCharacter.cpp и создадим тело для наших функций.

Также здесь есть функция, в которой мы получаем указатель на PlayerInputComponent, в этой функции мы будет "биндить" наши mapping с функциями MoveForward и MoveRight

У PlayerInputComponent есть функция BindAxis. В качестве первого параметра необходимо указать имя mapping, которые мы создавали ранее. Второй параметр - это указатель на объект, функция которого будет вызываться и третий параметр это ссылка на саму функцию.

Аналогично проделываем с MoveRight

Перейдем в тело функции MoveForward и воспользуемся там функцией AddMovementInput, которая и будет перемещать персонажа. Для нее нужно указать несколько параметров.

Первый, направление движения. Воспользуемся другой функцией(GetActorForwardVector), которая возвращает вектор куда смотрит Actor.

Второй, это наш Scale mapping'a от -1 до 1. На это число будет умножаться вектор направления, тем самым двигать персонажа в нужную сторону в зависимости от знака.

Тоже самое проделываем и с MoveRight. Только используем GetActorRightVector.

Осталось добавить управление камерой.

Для этого у PlayerInputComponent вызываем функции BindAxis для mapping'ов LookUp и Turn. В Unreal Engine есть встроенные функция для управления камерой, поэтому мы указываем ссылки на них.

Для LookUp - AddControllerPitchInput

Для Turn - AddControllerYawInput

На этом я заканчиваю. Если вам понравился контент, то буду рад вашей подписке, лайку или комменту:)

Тоже самое, только в видео

Подпишись:

Discord

VK

Youtube

Rutube

Комментарии (5)


  1. loginmen
    12.07.2022 16:17

    Я бы создавал SkeletalMeshComponent в C++ классе и проверял его в BeginPlay используя checkf. И спрашивается зачем нужен PlayerController если управление все равно пишется в самом игроке? Либо класс не нужен либо перенести в него управление (хотя такое лучше когда можно менять персонажей).

    Лучше добавить ссылку на прошлую часть в эту, так будет проще ориентироваться.
    Для проекта стоит использовать Git, очень странно видеть проект который его не использует, очень полезная привычка. А так же делиться кодом/проектом куда лучше, чем через облака (привет первая часть статьи)


    1. VlaKu Автор
      12.07.2022 17:19

      Привет, спасибо за замечания. Git я начал использовать чуть позже)


      1. loginmen
        13.07.2022 10:05

        Добавлю еще, что код в виде картинок не очень идея, код принято в виде текста выкладывать.
        И почему 4 а не 5 движок?


        1. VlaKu Автор
          13.07.2022 10:17

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


        1. VlaKu Автор
          13.07.2022 10:20

          Код в виде текста чуть позже отредактирую, спасибо за идею)