Почему С++, а не Blueprint?
Просмотрел и прочитал много статей про программирование на блупринтах, чтобы выяснить их место в создании игр на движке Unreal Engine 4 и в чем их преимущество перед традиционным программирование на языке программирования С++. Как оказалось это не конкурирующие подходы, а дополняющие один другой, при том в продакшене используется большей частью С++.Сами разработчики движка из Epic для своих игр используют эти две составляющие на разных этапах разработки игры. Сначала на блупринтах геймдизайнеры создают прототип игры, затем передают его программистам, которые для продакшена переписывают игру уже на С++. А раз сами разработчики движка предпочитают выпускать игры на С++, а не на чистых блупринтах, то значит и другие должны поступать также.
Само собой писать всё на С++ будет не правильно и нужно находить баланс между блупринтами и С++. Думаю это самый сложный момент, потому что по сути нет инструкций, когда надо использовать С++, а когда блупринты. Предполагаю, что Epic переписывают игру на С++, потому что блупринты уступают по скорости примерно в 8 раз, хотя позволяют разрабатывать игры быстрее.
В общем, я решил что надо осваивать С++ часть движка Unreal Engine 4 для того, чтобы разрабатывать свои игры. При том буду стремиться делать базовые "кирпичики" на С++, а уже в Blueprints из них создавать игру. Ну и как положено в программировании, первой программой будет Hello World. Далее делал этот проект по книге Carnall B. "Unreal Engine 4.x By Example".
Создание проекта Hello World на С++.
Создаю новый пустой проект на закладке С++, при этом оставляю дополнительный контент, чтобы из него потом можно было взять меш для шара, над которым будет моя надпись.Проект называется HelloCode.
Первый актер для проекта.
Так как мне надо, чтобы на сцене был шар, который был бы видим, то нужно создать новый класс, унаследованный от класса AActor. Это просто класс, который позволяет спавнить объект в игровой мир ( т.е. просто создавать объект, новый для меня термин, но похоже уже устоявшийся в разработке игр). AActor часто используется для статических объектов, типа стол, дерево и т.д., а у меня это будет шар. Назову новый класс HelloSphere и создам его через мастер классов С++, после чего автоматически откроется Visual Studio.Добавление компонентов в класс AHelloSphere.
Для того чтобы актер мог взаимодействовать с внешним миром, нужно добавить в него несколько компонентов, т.к. какой-либо функционал к актеру добавляется через компоненты. Можно использовать уже готовые компоненты или создать их самому. Компоненты в актера добавляются в его конструкторе с помощью функции CreateDefaultSubobject(), при том существует множество её вариантов. Компоненты создаются с её помощью, а не через оператор new, потому что это позволяет задействовать "сборщик мусора" из игрового движка и не беспокоится об уничтожении созданного компонента. Так же, создавая компоненты через CreateDefaultSubobject(), можно не добавлять члены класса в виде ссылок на компоненты в заголовочном файле.Компонент для вывода текста UTextRenderComponent.
Но среди добавляемых к актеру AHelloSphere компонентов, есть один, доступ к которому будет нужен после добавления его в конструкторе. Это компонент UTextRenderComponent, который выводит текст на сцене. Именно он будет показывать приветственную надпись. Надпись в нем должна меняться во время выполнения программы.Добавлю в заголовочный файл HelloSphere.h указатель на этот компонент.
protected: class UTextRenderComponent* TextRenderComponent;
Компонент коллизий USphereComponent.
Теперь нужно добавить компонент, который бы позволял отслеживать пересечение или столкновения актера HelloSphere с другими объектами. Для этих целей есть несколько компонентов, но мне подойдет тот что выглядит как шар. Его не видно на сцене во время работы программы, но в редакторе он отображается как линии в форме сферы. Называется он USphereComponent. Добавлю в конструктор по умолчанию следующий код:// Our root component will be a sphere component that will inform us of overlaps and collisions
USphereComponent* SphereComponent = CreateDefaultSubobject<USphereComponent>(TEXT("RootComponent"));
RootComponent = SphereComponent;
// Assign properties to sphere component
SphereComponent->InitSphereRadius(220.0f);
SphereComponent->SetCollisionProfileName(TEXT("OverlapAllDynamic"));
Тут используется CreateDefaultSubobject() как шаблонная функция, которая возвращает указатель на созданный компонент сферы, название, которого передается через параметр. Затем, компонент SphereComponent делается корневым компонентом RootComponent. Не разобрался пока какой компонент лучше делать корневым и на что это влияет, но важно присвоить значение RootComponent, если в актере используется несколько компонент. Далее укажем радиус сферы в виде числовой константы 220.0f. "f" в конце числа, означает, что это float значение.И в конце назначаем имя профилю коллизии (столкновению). Это позволяет определить как будет реагировать актер при пересечении с другими актерами. Этот параметр есть в редакторе и его можно изменять:
Компонент для статического меша UStaticMeshComponent.
Теперь нужно добавить компонент, который бы показывал на сцене меш актера. Так как актер будет представлен в виде шара без какой-либо анимации, т.е. неподвижный объект, то нужно использовать UStaticMeshComponent. Добавлю в конструктор актера необходимый для этого код:// Create and attach a sphere mesh
UStaticMeshComponent* SphereVisual = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("SphereMesh"));
SphereVisual->SetupAttachment(RootComponent);
// Assign mesh to static mesh component through construction helper
ConstructorHelpers::FObjectFinder<UStaticMesh>SphereAsset(TEXT("/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere"));
// Adjust properties of the mesh if mesh asset was found
if (SphereAsset.Succeeded())
{
SphereVisual->SetStaticMesh(SphereAsset.Object);
SphereVisual->SetRelativeLocation(FVector(0.0f, 0.0f, -50.0f));
}
Здесь был создан компонент статического меша и получен указатель на этот новый компонент (SphereVisual), после чего он был присоединен к корневому компоненту и таким образом образовалась иерархия. Корневым компонентом является коллизия, а его дочерним элементом статический меш, т.е. статический меш находится внутри коллизии.
В следующей строчке использовался FObjectFinder. Он позволяет найти добавленный в проект ассет через текстовую строку, в которой указывается путь. В данном случае это сфера, поставляемая вместе со стартовым комплектом.
Перед тем как начать устанавливать параметры для меша, необходимо убедиться, что такой меш существует и путь к нему был указан правильно. Это делается с помощью метода Succeeded(). Структура FObjectFinder содержит переменную Object, в которой хранится указатель на сам объект меша, мы должны установить его в компонент UStaticMeshComponent, через соответствующую функцию SetStaticMesh(). Затем с помощью функции SetRelativeLocation() изменим местоположение меша внутри корневого компонента, чтобы он оказался в центре компонента коллизии.
Теперь, после того как был уставлен и настроен компонент с мешем, можно скомпилировать проект и разместить шар на сцене.
Далее надо будет добавить эффект горения шара и надпись над ним.
П.С. Для того чтобы компилятор не выдавал ошибку про неизвестный класс, про то что нельзя выполнять операции над указателями с классом не полного типа и т.п. надо добавить объявления на заголовочные файлы этих классов.
#include "Components/SphereComponent.h" #include "Components/StaticMeshComponent.h" #include "UObject/ConstructorHelpers.h"
Для присоединения компонента меша к корневому компоненту в книге использовалась функция AttachTo(), но на данный момент это API уже устарело и вместо неё нужно использовать SetupAttachment() или AttachToComponent().
Привет миру из Unreal Engine 4 на C++. Часть 2.




Комментарии
Отправить комментарий