In-Depth Character Movement Using C++ And Blueprints – Unreal Engine

Table of Contents

In-Depth Character Movement Using C++ And Blueprints – Unreal Engine

Reading Time: 16 minutes
Level: Beginner – Intermediate

Help Others Learn Game Development

As the title of the post suggests we are going to create a character movement system in Unreal Engine.

I am going to show you how to create the movement system using blueprints as well as C++, so depending on your project if you are using only blueprints or only C++ or even a mix between the two, you will have everything you need to create the movement of your game character.

Download The Complete Project For This Tutorial

You can download the finished project for this tutorial by clicking on the Download assets button above.
 
It is not mandatory that you download the project, you can follow the tutorial without the project, but if you want to have the finished project for your own reference you can download it above.
 

Important Note Before We Start

One of the labels of this tutorial is beginner, but this tutorial is not for complete beginners who are working with Unreal Engine for the first time.

I expect you to know your way around Unreal Engine editor and that you know how to use blueprints and write basic C++ code and that you created at least one basic game in Unreal Engine.

Creating The Project

I am not going to use anything fancy when it comes to 3D models because everything that I will cover in this post you can use on any 3D model that you want to use for your game.

For the sake of simplicity I am going to use the third person project template, so make sure that you select it when you create your project:

Img 1
Make sure that you select C++ instead of Blueprints in the Project Settings. Give the project your desired name and click the Create Project button to create it:
 
Img 2


Setting Up The Project

I am going to use the default level that comes with the project template, and because of that I am going to make some preparations before we start creating our custom character.

First I am going to remove the default ThirdPersonCharacter blueprint from the level, just locate it in the World Outliner tab and press the Delete key on your keyboard:

Img 3

Inside the Content top folder, Right Click -> New Folder and name it Blueprints. Inside the Blueprints folder, Right Click -> Blueprint Class and in the Pick Parent Class window, expand the All Classes drop down list, filter for game mode and select GameMode as the parent class:

Img 4

Give the new blueprint name BP_CharacterMovement_GameMode. Next, go under Edit -> Project Settings.

In the Project Settings locate Maps & Modes and under Default Modes click on the Default GameMode drop down list and select BP_CharacterMovement_GameMode as the default game mode:

Img 5


Setting Up The Input

Since we selected the Third Person template the input is set by default. If you go to Edit -> Project Settings -> Input you will see all the Action and Axis Mappings:

Img 9

We don’t need all these defined inputs, so I am going to delete the ones we don’t need and leave the ones that we will use:

Img 10
I’ve left all the Action and Axis Mappings that we will use in this project and I also removed the unnecessary keys that were defined as triggers for certain Axis and Action Mappings and only left the ones that we will use.
 
Just as a note, we didn’t have to do all of this, we could have left the input settings as they are and only use the ones that we need, but I have a habit of removing everything I don’t need in the project, which is what I advice that you do as well, that is why I am teaching it here.
 

Preparing The Character Blueprint

First we are going to create the character movement system using a blueprint. So inside the Blueprints folder, Right Click -> Blueprint Class. Select the Character as the parent class:

Img 6

Name the new blueprint BP_Character and open it in the editor. In the Components tab select the Mesh component and in the Details tab under the Mesh settings for the Skeletal Mesh select the SK_Mannequin model that comes with the project, and under Animation settings for the Anim Class select ThirdPerson_AnimBP_C as the animation blueprint:

Img 7
In the Transform component change the values for the Z location and Z rotation of the Mesh component:
 
Img 8
Moving forward, we are going to attach a Spring Arm component to the BP_Character so click on the Add Component button and filter for spring arm:
 
Img 11

Now select the Spring Arm component and click on the Add Component button and filter for the camera:

Img 12

Make sure that the Camera component is a child of the Spring Arm component:

Img 13
Select the Camera component and change its Location and Rotation values in the Transform property from the Details tab:
 
Img 14

When are finished, this is how BP_Character blueprint looks like:

Img 15

The last step before we proceed to code the movement in the blueprint is to set our BP_Character as the Default Pawn Class in Project Settings -> Maps & Modes:

Img 16

We already created our BP_CharacterMovement_GameMode and we set it as the Default GameMode, that means we can also change the Default Pawn Class and set it to our BP_Character.

When we start working with C++ and when we create a blueprint out of the C++ class we will change the Default Pawn Class to that blueprint.

Creating The Movement And Rotation Via Blueprints

Starting with the movement, inside the Event Graph of BP_Character, add the following nodes:

Img 17

Yo can copy the nodes from here:

If you don’t know how to use blueprintUE tool to copy the nodes, you can learn that by clicking here.

First we get the rotation by calling Get Control Rotation function, because from the return value of that function we can get the forward and right vector rotation e.g. the rotation for the specified moving direction.

Next, we use the MoveForward and MoveRight input axis that are defined in Project Settings -> Input, and when they are triggered we are calling Add Movement Input function to make the actor move.

For that to happen, we need to provide the Scale Value which is either positive or negative and that will determine if the actor will move forward(positive), backward(negative), right(positive) or left(negative).

To determine the side where the actor will go, we need to pass the World Direction parameter which we can get from the Get Forward Vector and Get Right Vector, and the names of those vectors specify in which direction the actor will move.

This is everything we need to make the player actor move. Compile and Save the current blueprint and run the game to test it:

So the movement works and we can move the player actor left, right, forward and backwards, but we can’t rotate him.

To fix the rotation problem, we need to add the following nodes:

Img 18

You can copy the nodes from here:

The InputAxis Turn is triggered when we move the mouse horizontally, and when that happens we are going to call Add Controller Yaw Input to change the rotation of the player actor left and right.

The same thing we are doing with InputAxis LookUp which is triggered when we move the mouse vertically, but for this case, we are calling Add Controller Pitch Input to change the rotation of the player actor up and down:

While we can rotate left and right, we are not able to rotate up or down and we also have movement issues where the player actor sort of glitches while moving when we try to rotate up or down.

The issue is with the Spring Arm component that is holding the Camera. We need to open BP_Character in the editor, click on the Spring Arm component and in the Details tab locate the Camera Settings and check the checkbox for Use Pawn Control Rotation:

Img 19

Compile and Save the new changes and let’s test the game now:


Additional Rotation Tips

While we can rotate in all directions, there are still some things that can be corrected. For example, if we are not moving the mouse and the rotation is standing still, if the player actor moves to the side it looks like a robot that it running that doesn’t know how to turn around.

To fix this, we need to go inside the BP_Character blueprint, select the BP_Character(self) top parent component in the Components tab, then in the Details tab locate the Pawn settings and uncheck the Use Controller Rotation Yaw checkbox:

Img 20

Unchecking the User Controller Rotation Yaw checkbox will give the control over that rotation back to the blueprint itself and it will not be controller by the controller of the blueprint.

Next, we need to select the Character Movement component in the Components tab, and in the Details tab locate the Character Movement (Rotation Settings) and check the Orient Rotation to Movement checkbox:

Img 21

Orient Rotation To Movement will make sure that the actor is rotating towards the movement direction and it will fix the problem that we had. So let’s test the game now:

Now the player actor is rotating towards the direction where we are moving.

Another thing that we can do with the rotation is inverse it. If you run the game now and move the mouse up, the rotation will go up, if you move it down it will go down, which is what is suppose to happen.

But often in games, especially FPS games, you have an option in the settings to inverse the mouse which will make the rotation go in the opposite way e.g. when you move the mouse up the rotation goes down, and vice-versa.

To achieve this effect, all we have to do is go in the Project Settings -> Input, locate the Axis Mapping responsible for the rotation, and change the value of the Scale:

Img 22

Currently, the value is set to -1, you can change it to 1 and test the game. You will see that the rotation now is inverse. You can do the same thing for the horizontal rotation and for the movement as well, so that is something that you can experiment with.

Spring Arm Lag Settings

You can also play with the Lag settings for the Spring Arm component to make the Camera follow the player actor smoother.
 
Just select the Spring Arm component in the Components tab and in the Details tab locate the Lag settings:
 
IMg 25
The first thing you would need to do is enable the camera lag option by checking the Enable Camera Lag checkbox, from there you can play with option values and see the outcome.
 

Jumping Feature

The last step is to make the player actor jump, which is very simple to do because we already have a built in jump functionality in the Character class that we inherited from.

Open BP_Character in the blueprint editor and add the following nodes:

Img 23

You can copy the nodes from here:

You can run the game on your own and test out the jumping. Before we move on to C++, I am going to show where you can change the jump force, air control, and other settings related to the jumping and controlling the actor while in the air functionality.
 
Open BP_Character in the blueprint editor, select the Character Movement component from the Components tab, and in the Details tab locate the Character Movement: Jumping / Falling settings:
 
Img 24

You can play with different settings like Jump Z Velocity which will affect how far the actor can jump, air control will determine the amount of control you have over the actor while he is in the air and so on.

Just experiment with the numbers for different settings and then run the game to see the effect of the change that you made.

Player Character C++ Class

Moving on the C++ version of the movement, the first thing we will do is create the class. Inside the C++ Classes -> CharacterMovement folder Right Click -> New C++ Class.

Make sure that you inherit the Character class, then click the Next button:

Img 26

In the next window give the class a name PlayerCharacter and click the Create Class button:

Img 27

Open the PlayerCharacter.h file and at the bottom of the class add the following lines:

				
					public:

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera)
		class USpringArmComponent* CameraBoom;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera)
		class UCameraComponent* FollowCamera;
	
	void MoveForward(float Axis);
	void MoveRight(float Axis);
				
			

The Spring Arm and Camera components are the same ones we used in the blueprint in the first example of this tutorial.

The class keyword in front of them is called forward declaration and this is a really important concept to understand. If you don’t know what it is and why we use it, then make sure that you learn about that by clicking here.

The two functions MoveForward and MoveRight are going to be used to move the player actor in the game. Before we proceed to implement the code from PlayerCharacter.h file, make sure that you declare the two functions inside the PlayerCharacter.cpp file:

				
					void APlayerCharacter::MoveForward(float Axis)
{

}

void APlayerCharacter::MoveRight(float Axis)
{
	
}
				
			

You can either copy the functions above and paste them in the .cpp file, or you can follow this guide here that will show you a shortcut how to create definitions of functions inside the .cpp file.

Creating Components With C++ Code

With the declarations above, we have everything we need to start implementing the player’s movement.

Open the PlayerCharacter.cpp file, and at the top of the class, right below the last #include statement, add the following lines:

				
					#include "Components/InputComponent.h"
#include "GameFramework/Controller.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"
				
			
The first thing I always do in the .cpp file is add all the includes that I will use. The ones we added will allow us to use the functions from the specified classes in the include statement.
 
First we are going to create the Spring Arm and Camera components inside the constructor of the class:
 
				
					APlayerCharacter::APlayerCharacter()
{
 	// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("Camera Boom"));
	CameraBoom->SetupAttachment(RootComponent);

	CameraBoom->TargetArmLength = 300.0f;

	FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("Follow Camera"));
	FollowCamera->SetupAttachment(CameraBoom);
}
				
			
We use the CreateDefaultSubobject and pass the type of the object we want to create, in our case first we create the SpringArmComponent and then we create the CameraComponent on lines 6 and 11.
 
The SetupAttachment function will make the component a child of the specified component, so the SpringArmComponent will be a child of the RootComponent and the CameraComponent will be a child of the SpringArmComponent.
 
TargetArmLength is how far we are going to move the SpringArmComponent from the origin position which is (0, 0, 0).
 
Make sure that you compile this code by holding CTRL + SHIFT + B or CMD + SHIFT + B on MacOS, and don’t forget that you can also do it from the Unreal Engine editor.
 

Creating A Blueprint From The C++ Class

When the compiling finishes, go inside the editor and in the Content -> Blueprints folder Right Click -> Blueprint Class.
 
Expand the All Class drop down list and filter for playercharacter and make sure that you inherit the PlayerCharacter class and click the Select button:
 
Img 28

Name the new blueprint BP_Character_CPP so that we can differentiate it from the blueprint only one we created in the first example.

When you open the BP_Character_CPP in the blueprint editor you will notice that we already have the Spring Arm component named Camera Boom and the Camera component named Follow Camera in the Components tab:

Img 29
This is because of those lines of code we wrote in the constructor of the PlayerCharacter class. You will also notice that the Follow Camera e.g. Camera Component is the child of the Spring Arm or the Camera Boom component because we use the SetupAttachment function.
 
Moving forward, make sure that the Mesh component has the SK_Mannequin model attached in the Mesh settings and for its Anim Class attach the ThirdPerson_AnimBP_C.
 
Also make sure that you change the position and rotation of the Mesh component in the Transform property.
 
For this, you can follow the same instructions we had in the first part of this tutorial by clicking here.
 
Also, make sure that you change the default pawn to our newly created blueprint inside the Project Settings -> Maps & Modes:
 
Img 30
If you run the game now you will see our BP_Character_CPP spawned in the level, but you will not be able to move him. Let’s fix that.
 

Coding The Movement And Rotation Of The Player Actor

First, inside the SetupPlayerInputComponent function we are going to bind the functionality of the declared Axis Mappings to our functions:

				
					void APlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	PlayerInputComponent->BindAxis("MoveForward", this, &APlayerCharacter::MoveForward);
	PlayerInputComponent->BindAxis("MoveRight", this, &APlayerCharacter::MoveRight);
}
				
			

In blueprints, we used the following nodes to bind the functionality of the MoveForward and MoveRight Axis Mappings:

Img 31

In code, we use the lines above. The first parameter in the BindAxis function is the name of the Axis Mappings we declared in Project Settings -> Input:

Img 32

Keep in mind that the names you type for the Axis Mappings need to match with the same names you type in code, if you misspell the names then the binding will not work.

The second parameter, the keyword this, is referring to the class where the BindAxis function is called.

And the last parameter is the function in our class to which we are binding the Axis Mapping e.g. when we press the keys defined for the specific Axis Mapping the function we provide as the parameter will be executed.

In the two movement functions add the following lines:

				
					void APlayerCharacter::MoveForward(float Axis)
{
	FRotator Rotation = Controller->GetControlRotation();
	FRotator YawRotation(0.0f, Rotation.Yaw, 0.0f);

	FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
	AddMovementInput(ForwardDirection, Axis);
}

void APlayerCharacter::MoveRight(float Axis)
{
	FRotator Rotation = Controller->GetControlRotation();
	FRotator YawRotation(0.0f, Rotation.Yaw, 0.0f);

	FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
	AddMovementInput(RightDirection, Axis);
}
				
			
Same as what we did in the blueprint, first we need to get the direction vector. we use the Controller to get the rotation of the actor.
 
Then we create a new rotation variable by only using the Yaw(Z) rotation of the actor rotation that we got from the controller.
 
In order to get the forward direction, we use FRotationMatrix which a class that we can use to create a pure rotation without translation or scale. Ten we pass the YawRotation to FRotationMatrix because we want to create a pure rotation out of it, and then we call GetUnitAxis to convert the now pure YawRotation value to point to the forward direction.
 
After that we simply call the AddMovementInput function, passing to it the direction vector and the Axis parameter.
 
We do the same thing for the MoveRight function but instead of getting the forward vector we get the right vector.
 
Compile the code and run the game to test it:
 
As you can see from the preview above, we are able to move but we are not able to rotate the player actor.
 
Let’s fix that by adding the axis bindings for the rotation. Inside the SetupPlayerInputComponent function, add the following lines:
 
				
					void APlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	PlayerInputComponent->BindAxis("MoveForward", this, &APlayerCharacter::MoveForward);
	PlayerInputComponent->BindAxis("MoveRight", this, &APlayerCharacter::MoveRight);

	PlayerInputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);
	PlayerInputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);
}
				
			
The Turn and LookUp Axis Mappings are the ones we defined in Project Settings -> Input, and the same explanation we gave for the MoveForward and MoveRight apply here.
 
The AddControllerYawInput and AddControllerPitchInput functions from the Pawn class will make the player actor rotate left, right, up and down.
 
Compile the code and run the game:
 

The rotation now works and we can rotate with the mouse in all directions but the movement needs fixing because the player actor is not rotating towards the direction where he is going.

Fixing Rotation Issues And Additional Tips

To fix the rotation issue, we only need to set the orient rotation to movement to true in the Character Movement component which will make the player actor face the direction he is moving to. In the constructor add the following line of code:

				
					APlayerCharacter::APlayerCharacter()
{
 	// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("Camera Boom"));
	CameraBoom->SetupAttachment(RootComponent);

	CameraBoom->TargetArmLength = 300.0f;

	FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("Follow Camera"));
	FollowCamera->SetupAttachment(CameraBoom);
	
	GetCharacterMovement()->bOrientRotationToMovement = true;
}
				
			

Compile the code and run the game to test it:

We can also do this inside the blueprint editor, just select the Character Movement component in the Components tab and in the Details tab locate the Orient Rotation To Movement checkbox and check it.

Keep in mind for this rotation to work, we need to make sure that we turn off use control rotation for Pitch, Yaw, and Roll for the player actor. This can be done in the blueprint by selecting the BP_PlayerCharacter_CPP top parent, and in the Details tab locate the Pawn settings:

Img 33

The code equivalent for this are the following lines of code:

				
					bUseControllerRotationPitch = false;
	bUseControllerRotationYaw = false;
	bUseControllerRotationRoll = false;
				
			
Make sure that you add these lines of code in the constructor of the PlayerCharacter.cpp file.
 
We also need to make sure that the Spring Arm component is using the pawn’s control rotation and that the Camera component is not using the pawn’s control rotation. We did this with blueprints here, and the code version goes like this:
 
				
					CameraBoom->bUsePawnControlRotation = true;
	FollowCamera->bUsePawnControlRotation = false;
				
			


Additional Movement Tips

Same as how you can change the movement values for the Character Movement component via blueprints, you can do it via code. So you can experiment with some values such as the rotation rate, movement speed, and so on:
 
				
					GetCharacterMovement()->RotationRate = FRotator(0.0f, 360.0f, 0.0f);
	GetCharacterMovement()->JumpZVelocity = 600.0f;
	GetCharacterMovement()->AirControl = 0.2f;
				
			
Don’t forget that you set this code up in the constructor of the .cpp file for the specific class.
 

Jumping Functionality With C++

The last step is to add the jumping functionality in the SetupPlayerInputComponent:
 
				
					PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
	PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);
				
			
For the BindAction we have an additional parameter which is the IE_Pressed and IE_Released and they are self explanatory. The IE_Pressed will execute when the specified button we declared for the action is pressed, and the IE_Released will execute when that same button is released.
 
As a reference, I will leave the whole PlayerCharacter.cpp file class for you to copy or compare your code with mine:
 
				
					#include "PlayerCharacter.h"

#include "Components/InputComponent.h"
#include "GameFramework/Controller.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"

// Sets default values
APlayerCharacter::APlayerCharacter()
{
 	// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("Camera Boom"));
	CameraBoom->SetupAttachment(RootComponent);

	CameraBoom->TargetArmLength = 300.0f;

	FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("Follow Camera"));
	FollowCamera->SetupAttachment(CameraBoom);

	CameraBoom->bUsePawnControlRotation = true;
	FollowCamera->bUsePawnControlRotation = false;

	bUseControllerRotationPitch = false;
	bUseControllerRotationYaw = false;
	bUseControllerRotationRoll = false;

	GetCharacterMovement()->bOrientRotationToMovement = true;
	GetCharacterMovement()->RotationRate = FRotator(0.0f, 360.0f, 0.0f);
	GetCharacterMovement()->JumpZVelocity = 600.0f;
	GetCharacterMovement()->AirControl = 0.2f;

}

// Called when the game starts or when spawned
void APlayerCharacter::BeginPlay()
{
	Super::BeginPlay();
	
}

// Called every frame
void APlayerCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

// Called to bind functionality to input
void APlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	PlayerInputComponent->BindAxis("MoveForward", this, &APlayerCharacter::MoveForward);
	PlayerInputComponent->BindAxis("MoveRight", this, &APlayerCharacter::MoveRight);

	PlayerInputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);
	PlayerInputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);

	PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
	PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);

}

void APlayerCharacter::MoveForward(float Axis)
{
	FRotator Rotation = Controller->GetControlRotation();
	FRotator YawRotation(0.0f, Rotation.Yaw, 0.0f);

	FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
	AddMovementInput(ForwardDirection, Axis);
}

void APlayerCharacter::MoveRight(float Axis)
{
	FRotator Rotation = Controller->GetControlRotation();
	FRotator YawRotation(0.0f, Rotation.Yaw, 0.0f);

	FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
	AddMovementInput(RightDirection, Axis);
}
				
			

Make sure that you compile the code before you run the game to test it. And there you have it, a complete basic and intermediate movement system for your game characters in Unreal Engine.

Leave a Comment