Quantcast
Channel: Kodeco | High quality programming tutorials: iOS, Android, Swift, Kotlin, Unity, and more
Viewing all articles
Browse latest Browse all 4370

Unreal Engine 4 C++ Tutorial

$
0
0

Unreal Engine 4 C++ Tutorial

Blueprints is a very popular way to create gameplay in Unreal Engine 4. However, if you’re a long-time programmer and prefer sticking to code, C++ is for you! Using C++, you can also make changes to the engine and also make your own plugins.

In this tutorial, you will learn how to:

  • Create C++ classes
  • Add components and make them visible to Blueprints
  • Create a Blueprint class based on a C++ class
  • Add variables and make them editable in Blueprints
  • Bind axis and action mappings to functions
  • Override C++ functions in Blueprints
  • Bind an overlap event to a function

Please note that this is not a tutorial on learning C++. Instead, this tutorial will focus on working with C++ in the context of Unreal Engine.

Note: This tutorial assumes you already know the basics of using Unreal Engine. If you are new to Unreal Engine, you should go through our 10-part Unreal Engine for Beginners tutorial series first.

Getting Started

If you haven’t already, you will need to install Visual Studio. Follow Epic’s official guide on setting up Visual Studio for Unreal Engine 4. (Although you can use alternative IDEs, this tutorial will use Visual Studio as Unreal is already designed to work with it.)

Afterwards, download the starter project and unzip it. Navigate to the project folder and open CoinCollector.uproject. If it asks you to rebuild modules, click Yes.

Unreal Engine 4 C++ Tutorial

Once that is done, you will see the following scene:

Unreal Engine 4 C++ Tutorial

In this tutorial, you will create a ball that the player will control to collect coins. In previous tutorials, you have been creating player-controlled characters using Blueprints. For this tutorial, you will create one using C++.

Creating a C++ Class

To create a C++ class, go to the Content Browser and select Add New\New C++ Class.

Unreal Engine 4 C++ Tutorial

This will bring up the C++ Class Wizard. First, you need to select which class to inherit from. Since the class needs to be player-controlled, you will need a Pawn. Select Pawn and click Next.

Unreal Engine 4 C++ Tutorial

In the next screen, you can specify the name and path for your .h and .cpp files. Change Name to BasePlayer and then click Create Class.

Unreal Engine 4 C++ Tutorial

This will create your files and then compile your project. After compiling, Unreal will open Visual Studio. If BasePlayer.cpp and BasePlayer.h are not open, go to the Solution Explorer and open them. You can find them under Games\CoinCollector\Source\CoinCollector.

Unreal Engine 4 C++ Tutorial

Before we move on, you should know about Unreal’s reflection system. This system powers various parts of the engine such as the Details panel and garbage collection. When you create a class using the C++ Class Wizard, Unreal will put three lines into your header:

  1. #include "TypeName.generated.h"
  2. UCLASS()
  3. GENERATED_BODY()

Unreal requires these lines in order for a class to be visible to the reflection system. If this sounds confusing, don’t worry. Just know that the reflection system will allow you to do things such as expose functions and variables to Blueprints and the editor.

You’ll also notice that your class is named ABasePlayer instead of BasePlayer. When creating an actor-type class, Unreal will prefix the class name with A (for actor). The reflection system requires classes to have the appropriate prefixes in order to work. You can read about the other prefixes in Epic’s Coding Standard.

Note: Prefixes will not display within the editor. For example, if you wanted to create a variable of type ABasePlayer, you would search for BasePlayer.

That’s all you need to know about the reflection system for now. Next, you will add a player model and camera. To do this, you need to use components.

Adding Components

For the player Pawn, you will add three components:

  1. Static Mesh: This will allow you to select a mesh to represent the player
  2. Spring Arm: This component operates like a camera boom. One end will be attached to the mesh and the camera will be attached to the other end.
  3. Camera: Whatever this camera sees is what Unreal will display to the player

First, you need to include headers for each type of component. Open BasePlayer.h and then add the following lines above #include "BasePlayer.generated.h":

#include "Components/StaticMeshComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
Note: It is important that the .generated.h file is the last include. In this case, your includes should look like this:
#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "Components/StaticMeshComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "BasePlayer.generated.h"

If it is not the last include, you will get an error when compiling.

Now you need to declare variables for each component. Add the following lines after SetupPlayerInputComponent():

UStaticMeshComponent* Mesh;
USpringArmComponent* SpringArm;
UCameraComponent* Camera;

The name you use here will be the name of the component in the editor. In this case, the components will display as Mesh, SpringArm and Camera.

Next, you need to make each variable visible to the reflection system. To do this, add UPROPERTY() above each variable. Your code should now look like this:

UPROPERTY()
UStaticMeshComponent* Mesh;

UPROPERTY()
USpringArmComponent* SpringArm;

UPROPERTY()
UCameraComponent* Camera;

You can also add specifiers to UPROPERTY(). These will control how the variable behaves with various aspects of the engine.

Add VisibleAnywhere and BlueprintReadOnly inside the brackets for each UPROPERTY(). Separate each specifier with a comma.

UPROPERTY(VisibleAnywhere, BlueprintReadOnly)

VisibleAnywhere will allow each component to be visible within the editor (including Blueprints).

BlueprintReadOnly will allow you to get a reference to the component using Blueprint nodes. However, it will not allow you to set the component. It is important for components to be read-only because their variables are pointers. You do not want to allow users to set this otherwise they could point to a random location in memory. Note that BlueprintReadOnly will still allow you to set variables inside of the component, which is the desired behavior.

Note: For non-pointer variables (int, float, boolean etc.), use EditAnywhere and BlueprintReadWrite instead.

Now that you have variables for each component, you need to initialize them. To do this, you must create them within the constructor.

Initializing Components

To create components, you can use CreateDefaultSubobject<Type>("InternalName"). Open BasePlayer.cpp and add the following lines inside ABasePlayer():

Mesh = CreateDefaultSubobject<UStaticMeshComponent>("Mesh");
SpringArm = CreateDefaultSubobject<USpringArmComponent>("SpringArm");
Camera = CreateDefaultSubobject<UCameraComponent>("Camera");

This will create a component of each type. It will then assign their memory address to the provided variable. The string argument will be the component’s internal name used by the engine (not the display name although they are the same in this case).

Next you need to set up the hierarchy (which component is the root and so on). Add the following after the previous code:

RootComponent = Mesh;
SpringArm->SetupAttachment(Mesh);
Camera->SetupAttachment(SpringArm);

The first line will make Mesh the root component. The second line will attach SpringArm to Mesh. Finally, the third line will attach Camera to SpringArm.

Now that the component code is complete, you need to compile. Perform one of the following methods to compile:

  1. In Visual Studio, select Build\Build Solution
  2. In Unreal Engine, click Compile in the Toolbar

Next, you need to set which mesh to use and the rotation of the spring arm. It is advisable to do this in Blueprints because you do not want to hard-code asset paths in C++. For example, in C++, you would need to do something like this to set a static mesh:

static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshToUse(TEXT("StaticMesh'/Game/MyMesh.MyMesh");
MeshComponent->SetStaticMesh(MeshToUse.Object);

However, in Blueprints, you can just select a mesh from a drop-down list.

Unreal Engine 4 C++ Tutorial

If you were to move the asset to another folder, your Blueprints wouldn’t break. However, in C++, you would have to change every reference to that asset.

To set the mesh and spring arm rotation within Blueprints, you will need to create a Blueprint based on BasePlayer.

Note: It is common practice to create base classes in C++ and then create a Blueprint subclass. This makes it easier for roles such as artists and designers to edit classes.

Subclassing C++ Classes

In Unreal Engine, navigate to the Blueprints folder and create a Blueprint Class. Expand the All Classes section and search for BasePlayer. Select BasePlayer and then click Select.

Unreal Engine 4 C++ Tutorial

Rename it to BP_Player and then open it.

First, you will set the mesh. Select the Mesh component and set its Static Mesh to SM_Sphere.

Unreal Engine 4 C++ Tutorial

Next, you need to set the spring arm’s rotation and length. This will be a top-down game so the camera needs to be above the player.

Select the SpringArm component and set Rotation to (0, -50, 0). This will rotate the spring arm so that the camera points down towards the mesh.

Unreal Engine 4 C++ Tutorial

Since the spring arm is a child of the mesh, it will start spinning when the ball starts spinning.

Unreal Engine 4 C++ Tutorial

To fix this, you need to set the rotation of the spring arm to be absolute. Click the arrow next to Rotation and select World.

Unreal Engine 4 C++ Tutorial

Afterwards, set Target Arm Length to 1000. This will place the camera 1000 units away from the mesh.

Unreal Engine 4 C++ Tutorial

Next, you need to set the Default Pawn Class in order to use your Pawn. Click Compile and then go back to the editor. Open the World Settings and set Default Pawn to BP_Player.

Unreal Engine 4 C++ Tutorial

Press Play to see your Pawn in the game.

Unreal Engine 4 C++ Tutorial

The next step is to add functions so the player can move around.

Implementing Movement

Instead of adding an offset to move around, you will move around using physics! First, you need a variable to indicate how much force to apply to the ball.

Go back to Visual Studio and open BasePlayer.h. Add the following after the component variables:

UPROPERTY(EditAnywhere, BlueprintReadWrite)
float MovementForce;

EditAnywhere allows you to edit MovementForce in the Details panel. BlueprintReadWrite will allow you to set and read MovementForce using Blueprint nodes.

Next, you will create two functions. One for moving up and down and another for moving left and right.

Creating Movement Functions

Add the following function declarations below MovementForce:

void MoveUp(float Value);
void MoveRight(float Value);

Later on, you will bind axis mapppings to these functions. By doing this, axis mappings will be able to pass in their scale (which is why the functions need the float Value parameter).

Note: If you are not familiar with axis mappings and scale, check out our Blueprints tutorial.

Now, you need to create an implementation for each function. Open BasePlayer.cpp and add the following at the end of the file:

void ABasePlayer::MoveUp(float Value)
{
	FVector ForceToAdd = FVector(1, 0, 0) * MovementForce * Value;
	Mesh->AddForce(ForceToAdd);
}

void ABasePlayer::MoveRight(float Value)
{
	FVector ForceToAdd = FVector(0, 1, 0) * MovementForce * Value;
	Mesh->AddForce(ForceToAdd);
}

MoveUp() will add a physics force on the X-axis to Mesh. The strength of the force is provided by MovementForce. By multiplying the result by Value (the axis mapping scale), the mesh can move in either the positive or negative directions.

MoveRight() does the same as MoveUp() but on the Y-axis.

Now that the movement functions are complete, you need to bind the axis mappings to them.

Binding Axis Mappings to Functions

For the sake of simplicity, I have already created the axis mappings for you. You can find them in the Project Settings under Input.

Unreal Engine 4 C++ Tutorial

Note: Axis mappings do not need to have the same name as the function you are binding them to.

Add the following inside SetupPlayerInputComponent():

InputComponent->BindAxis("MoveUp", this, &ABasePlayer::MoveUp);
InputComponent->BindAxis("MoveRight", this, &ABasePlayer::MoveRight);

This will bind the MoveUp and MoveRight axis mappings to MoveUp() and MoveRight().

That’s it for the movement functions. Next, you need to enable physics on the Mesh component.

Enabling Physics

Add the following lines inside ABasePlayer():

Mesh->SetSimulatePhysics(true);
MovementForce = 100000;

The first line will allow physics forces to affect Mesh. The second line will set MovementForce to 100,000. This means 100,000 units of force will be added to the ball when moving. By default, physics objects weigh about 110 kilograms so you need a lot of force to move them!

If you’ve created a subclass, some properties won’t change even if you’ve changed it within the base class. In this case, BP_Player won’t have Simulate Physics enabled. However, any subclasses you create now will have it enabled by default.

Compile and then go back to Unreal Engine. Open BP_Player and select the Mesh component. Afterwards, enable Simulate Physics.

Unreal Engine 4 C++ Tutorial

Click Compile and then press Play. Use W, A, S and D to move around.

Unreal Engine 4 C++ Tutorial

Next, you will declare a C++ function that you can implement using Blueprints. This allows designers to create functionality without having to use C++. To learn this, you will create a jump function.

Creating the Jump Function

First you need to bind the jump mapping to a function. In this tutorial, jump is set to space bar.

Unreal Engine 4 C++ Tutorial

Go back to Visual Studio and open BasePlayer.h. Add the following below MoveRight():

UPROPERTY(EditAnywhere, BlueprintReadWrite)
float JumpImpulse;

UFUNCTION(BlueprintImplementableEvent)
void Jump();

First is a float variable called JumpImpulse. You will use this when implementing the jump. It uses EditAnywhere to make it editable within the editor. It also uses BlueprintReadWrite so you can read and write it using Blueprint nodes.

Next is the jump function. UFUNCTION() will make Jump() visible to the reflection system. BlueprintImplementableEvent will allow Blueprints to implement Jump(). If there is no implementation, any calls to Jump() will do nothing.

Note: If you want to provide a default implementation in C++, use BlueprintNativeEvent instead. You’ll learn how to do this later on in the tutorial.

Since Jump is an action mapping, the method to bind it is slightly different. Close BasePlayer.h and then open BasePlayer.cpp. Add the following inside SetupPlayerInputComponent():

InputComponent->BindAction("Jump", IE_Pressed, this, &ABasePlayer::Jump);

This will bind the Jump mapping to Jump(). It will only execute when you press the jump key. If you want it to execute when the key is released, use IE_Released instead.

Up next is overriding Jump() in Blueprints.

Overriding Functions in Blueprints

Compile and then close BasePlayer.cpp. Afterwards, go back to Unreal Engine and open BP_Player. Go to the My Blueprints panel and hover over Functions to display the Override drop-down. Click it and select Jump. This will create an Event Jump.

Unreal Engine 4 C++ Tutorial

Note: An override will be an event if there is no return type. If there is a return type, it will be a function.

Next, create the following setup:

Unreal Engine 4 C++ Tutorial

This will add an impulse (JumpImpulse) on the Z-axis to Mesh. Note that in this implementation, the player can jump indefinitely.

Next, you need to set the value of JumpImpulse. Click Class Defaults in the Toolbar and then go to the Details panel. Set JumpImpulse to 100000.

Unreal Engine 4 C++ Tutorial

Click Compile and then close BP_Player. Press Play and jump around using space bar.

Unreal Engine 4 C++ Tutorial

In the next section, you will make the coins disappear when the player touches them.

Collecting Coins

To handle overlaps, you need to bind a function to an overlap event. To do this, the function must meet two requirements. The first is that the function must have the UFUNCTION() macro. The second requirement is the function must have the correct signature. In this tutorial, you will use the OnActorBeginOverlap event. This event requires a function to have the following signature:

FunctionName(AActor* OverlappedActor, AActor* OtherActor)

Go back to Visual Studio and open BaseCoin.h. Add the following below PlayCustomDeath():

UFUNCTION()
void OnOverlap(AActor* OverlappedActor, AActor* OtherActor);

After binding, OnOverlap() will execute when the coin overlaps another actor. OverlappedActor will be the coin and OtherActor will be the other actor.

Next, you need to implement OnOverlap().

Implementing Overlaps

Open BaseCoin.cpp and add the following at the end of the file:

void ABaseCoin::OnOverlap(AActor* OverlappedActor, AActor* OtherActor)
{
}

Since you only want to detect overlaps with the player, you need to cast OtherActor to ABasePlayer. Before you do the cast, you need to include the header for ABasePlayer. Add the following below #include "BaseCoin.h":

#include "BasePlayer.h"

Now you need to perform the cast. In Unreal Engine, you can cast like this:

Cast<TypeToCastTo>(ObjectToCast);

If the cast is successful, it will return a pointer to ObjectToCast. If unsuccessful, it will return nullptr. By checking if the result is nullptr, you can determine if the object was of the correct type.

Add the following inside OnOverlap():

if (Cast<ABasePlayer>(OtherActor) != nullptr)
{
	Destroy();
}

Now, when OnOverlap() executes, it will check if OtherActor is of type ABasePlayer. If it is, destroy the coin.

Next, you need to bind OnOverlap().

Binding the Overlap Function

To bind a function to an overlap event, you need to use AddDynamic() on the event. Add the following inside ABaseCoin():

OnActorBeginOverlap.AddDynamic(this, &ABaseCoin::OnOverlap);

This will bind OnOverlap() to the OnActorBeginOverlap event. This event occurs whenever this actor overlaps another actor.

Compile and then go back to Unreal Engine. Press Play and start collecting coins. When you overlap a coin, the coin will destroy itself, causing it to disappear.

Unreal Engine 4 C++ Tutorial

Note: If the coins don’t disappear, try restarting the editor to do a full recompile. Some code changes require a restart in order to work.

In the next section, you will create another overridable C++ function. However, this time you will also create a default implementation. To demonstrate this, you will use OnOverlap().

Creating a Function’s Default Implementation

To make a function with a default implementation, you need to use the BlueprintNativeEvent specifier. Go back to Visual Studio and open BaseCoin.h. Add BlueprintNativeEvent to the UFUNCTION() of OnOverlap():

UFUNCTION(BlueprintNativeEvent)
void OnOverlap(AActor* OverlappedActor, AActor* OtherActor);

To make a function the default implementation, you need to add the _Implementation suffix. Open BaseCoin.cpp and change OnOverlap to OnOverlap_Implementation:

void ABaseCoin::OnOverlap_Implementation(AActor* OverlappedActor, AActor* OtherActor)

Now, if a child Blueprint does not implement OnOverlap(), this implementation will be used instead.

The next step is to implement OnOverlap() in BP_Coin.

Creating the Blueprint Implementation

For the Blueprint implementation, you will call PlayCustomDeath(). This C++ function will increase the coin’s rotation rate. After 0.5 seconds, the coin will destroy itself.

To call a C++ function from Blueprints, you need to use the BlueprintCallable specifier. Close BaseCoin.cpp and then open BaseCoin.h. Add the following above PlayCustomDeath():

UFUNCTION(BlueprintCallable)

Compile and then close Visual Studio. Go back to Unreal Engine and open BP_Coin. Override On Overlap and then create the following setup:

Unreal Engine 4 C++ Tutorial

Now whenever a player overlaps a coin, Play Custom Death will execute.

Click Compile and then close BP_Coin. Press Play and collect some coins to test the new implementation.

unreal engine C++ tutorial

Where to Go From Here?

You can download the completed project here.

As you can see, working with C++ in Unreal Engine is quite easy. Although you’ve accomplished a lot so far with C++, there is still a lot to learn! I’d recommend checking out Epic’s tutorial series on creating a top-down shooter using C++.

If you’re new to Unreal Engine, check out our 10-part beginner series. This series will take you through various systems such as Blueprints, Materials and Particle Systems.

If there’s a topic you’d like me to cover, let me know in the comments below!

The post Unreal Engine 4 C++ Tutorial appeared first on Ray Wenderlich.


Viewing all articles
Browse latest Browse all 4370

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>