100% found this document useful (1 vote)
962 views38 pages

Unreal Engine C++ Complete Guide - Tom Looman

Uploaded by

formidableerror
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
962 views38 pages

Unreal Engine C++ Complete Guide - Tom Looman

Uploaded by

formidableerror
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 38

Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.

com/unreal-engine-cpp-guide/

Tom Looman
Home > C++ / Tutorials / Unreal Engine

Unreal Engine C++ Complete Guide


READING TIME� 28 MINUTES  FEBRUARY 14, 2023  MARCH 11, 2024
 C++ / TUTORIALS / UNREAL ENGINE  COMMENTS� 11

Ge�ing started with Unreal Engine C++ can be a bit of a struggle. The resources online
have no clear path to follow or fail to explain the Unrealisms you’ll encounter. In this article,
I’ll a�empt to give you an overview of many unique aspects of Unreal’s C++ and brie�y go
over some of the native C++ features and how they are used in the context of Unreal
Engine. It’s a compilation of the many di�erent concepts that you will face when working in
C++ and Unreal Engine speci�cally.

This article can be used as a reference guide in your Unreal Engine C++ journey and as a
companion to the documentation and video tutorials/courses out there.

Disclaimer: this guide is not exhaustive in teaching you programming from the
ground up. This guide should help you understand the speci�cs of C++ within
Unreal Engine. To have a starting point and reference guide while diving into the
hands-on tutorials that demonstrate the practical use of C++ for your game.

THIS GUIDE IS LONG, DON’T FORGET TO BOOKMARK IT!

Page Contents
C++ vs. Blueprints
C++ Syntax & Symbols
Asterisk ‘*’ (Pointers)
Period ‘.’ and Arrow operator ‘�’ (Accessing Variables/Functions)
Double Colon ‘::’
Ampersand ‘&’ (References & Address operator)
Public, Protected, Private
Forward Declaring Classes

1 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

Casting (Cast<T>)
Interfaces
Delegates (Events)
Declaring and Using Delegates
Multicast Dynamic
Public/Private Folders
Class Pre�xes (F, A, U, E, G, T, …)
Project Pre�xes
Common Engine Types
FString, FName, FText
FVector, FRotator, FTransform �FQuat)
TArray, TMap, TSet
TSubclassOf<T>
C++ MACROS (& Unreal Property System)
UFUNCTION()
UPROPERTY()
GENERATED_BODY()
USTRUCT, UCLASS, UENUM
UE_LOG (Logging)
Modules
Why use modules?
Garbage Collection (Memory Management)
Automatic Updating of References (Actors & ActorComponents)
TWeakObjPtr<T> �UObjects)
Class Default Object
Asserts (Debugging)
Core Redirects
On The Horizon…

Ready to become an Unreal Engine C++ master? Don’t miss this limited-time o�er
to j o i n my c o m p r e h e n s i ve c o u r s e a n d a c c e l e r a te yo u r l e a r n i n g j o u r n e y !

C++ vs. Blueprints


Before we begin, a quick word on C++ vs. Blueprint. It’s the most common discussion in the
community. I love C++ and Blueprint and heavily use both. Building a solid foundation in C+
+ (your framework) and creating small game-speci�c ‘scripts’ on top using Blueprint is an
extremely powerful combination.

2 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

While Blueprint in Unreal Engine is a powerful scripting tool for anyone looking to build
games, learning C++ unlocks the full potential of the engine. Not every feature is exposed
to Blueprint, for certain things you still need C++. Certain game features may just be
easier to build and maintain in C++ in the �rst place. Not to mention the potential
performance gain of using code over Blueprint for the core systems of your game.

“In the early days, I went deep into C++ and tried to do pre�y much everything with it,
disregarding the power of Blueprint. In hindsight, this made my code more rigid than it
needed to be and removed some �exibility for others to make adjustments without
C++ knowledge. I later focused more on a healthy balance to great e�ect.”

Building the foundational systems (eg. inventory system, world interaction, etc.) in C+
+ and using these systems in Blueprint to tie it all together. This is now a large focus
of my course, where we build the foundational game framework and ability system to
allow �exible and small Blueprints to be created on top for individual features/
abilities, etc.

Alex Forsy the has a great video explaining how C++ and Blueprint �t together and why
you should use both instead of evangelizing one and dismissing the other.

C++ Syntax & Symbols


Throughout the article, I’ll be using code snippets as concrete examples. You can �nd
the reference game example project over on GitHub. You can freely browse this
repository to see more examples of how C++ is used with Unreal Engine.

While looking at C++ tutorials, you may be wondering about a few common symbols. I will
explain their meaning and use cases without going too deep into their technical details. I’ll
explain how they are most commonly used within Unreal Engine gameplay programming,
not C++ programming in general.

Asterisk ‘*’ (Pointers)


Commonly known as “pointers”, they may sound scarier than they actually are within
Unreal Engine, as most memory management is being taken care of while we’re dealing
with gameplay programming. Most commonly used to access objects like Actors in your

3 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

level and references to assets in your content folders such as sound e�ects or particle
systems.

Pointers to Objects
The �rst way you’ll be using pointers is to access and track instances of your objects. In
order to access your player, you’ll keep a pointer to the player class. For example,
AMyCharacter* MyPlayer;

// Get pointer to player controller, points to somewhere in memory


containing all data about the object.
APlayerController* PC = GetWorld()->GetPlayerController();

After running this code, the ‘PC’ variable is now pointing to the same place in memory as
the player controller we retrieved from World. We didn’t duplicate anything or create
anything new, we just looked up where to �nd the object we need, and can now use it to
do stu� for us such as calling functions on it or accessing its variables.

// Example function that tries to get the Actor underneath the player
crosshair if there is any
AActor* FocusedActor = GetFocusedInteractionActor();
if (FocusedActor != nullptr)
{
FocusedActor->Interact();
}
// alternative shorthand to check if pointer is valid is simply
if (FocusedActor)
{
FocusedActor->Interact();
}

It’s important to check if pointers are not “null” (also wri�en as “nullptr” in code, meaning
not pointing to anything) before a�empting to call functions or change its variables, or
the engine will crash when executing that piece of code. So you will use the above if-
statement often.

Perhaps even more important than knowing when to check for nullptr’s, is when
N OT to i n c l u d e n u l l p t r c h e c k s .

You should generally only check for nullptr if it’s likely and acceptable that a pointer is
in fact null and continue execution of the rest of the game regardless. In the above

4 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

code example, the FocusedActor* is going to be null in many cases, whenever there is
no interactable Actor under the player’s crosshair.

Now imagine in the example below we return a nullptr from GetPlayerController() and
(quietly) skip the if-statement where we would otherwise add an item to inventory.
Further down the line, you will scratch your head wondering why you didn’t receive
this item. Having no player controller is unlikely enough in most cases that when it
does happen, you may be be�er o� failing entirely as the state of the game is already
broken.

APlayerController* PC = GetWorld()->GetPlayerController();
if (PC)
{
PC->AddToInventory(NewItem);
}

For more info on this concept, I recommend Ari Arnbjörnsson’s talk (at 22:48�.

When creating components to be used in your Actor classes we use similar syntax. In the
header �le, we de�ne a pointer to a component, this will be a nullptr until we assign it an
instance of the component. Here is an example from the header of SCharacter.h where we
de�ne a CameraComponent . (See “ObjectPtr<T>” further down in this article which will
replace using raw pointers in headers in future releases of UE5�

UPROPERTY(VisibleAnywhere)
UCameraComponent* CameraComp;

Now in the SCharacter.cpp constructor (called during spawning/instantiation of the


Character class), we create an instance of the CameraComponent.

// This function is only used within constructors to create new instances


of our components. Outside of the constructor we use NewObject<T>();
CameraComp = CreateDefaultSubobject<UCameraComponent>("CameraComp");
// We can now safely call functions on the component
CameraComp->SetupAttachment(SpringArmComp);

We have now created and assigned an instance to the CameraComp variable.

If you want to create a new object outside the constructor, you instead use

5 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

NewObject<T>(), and for creating and spawning Actors use GetWorld()-


>SpawnActor<T>() where T is the class you want to spawn such as ASCharacter .

TObjectPtr<T>
In Unreal Engine 5 a new concept was introduced called TObjectPtr to replace raw
pointers (eg. UCameraComponent* ) in header �les with UProperties. This bene�ts the
new systems such as virtualized assets among other things which is why it’s the new
standard moving forward. The example above will now look as follows.

UPROPERTY(VisibleAnywhere)
TObjectPtr<UCameraComponent> CameraComp;

These bene�ts are for the editor only and in shipped builds it will function identically to
raw pointers. You may continue to use raw pointers, but it’s advised by Epic to move over to
using TObjectPtr whenever possible.

TObjectPtr<T> is only for the member properties in the headers, your C++ code in
.cpp �les continues to use raw pointers as there is no bene�t to using TObjectPtr in
functions and short-lived scope.

Pointers to Assets
The other common way to use pointers is to reference assets. These don’t represent
instances in your world/level, but instead point to loaded content in memory such as
textures, sound e�ects, meshes, etc. (it’s still pointing to an object, which in this case is
the class representing a piece of content or an “in-memory representation of an asset on
disk”).

Much like the previous example of the Camera Component, in Unreal Engine 5 you will
use TObjectPtr<UParticleSystem> instead of UParticleSystem* (raw pointer) to
reference assets. The raw pointers continue to work and shipped builds will
e�ectively use raw pointers again automatically.

We can take a projectile a�ack ability as an example that references a particle system.
The header de�nes the ParticleSystem pointer:

6 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

/* Particle System played during attack animation */


UPROPERTY(EditAnywhere, Category = "Attack")
UParticleSystem* CastingEffect;
// Can point to an asset in our content folder, will be assigned something
via the editor, not in the constructor as we did with components

Note that this pointer is going to be empty ( nullptr ) unless we assigned it to a speci�c
ParticleSystem via the Editor. That’s why we add UPROPERTY(EditAnywhere) to expose
the variable to be assigned in the editor.

Now in the class �le of the projectile a�ack (line 28�, we can use this asset pointer to
spawn the speci�ed ParticleSystem:

UGameplayStatics::SpawnEmitterAttached(CastingEffect, Character->GetMesh(), HandSocketN

Note: In this example, we didn’t check whether CastingE�ect is a nullptr before


a�empting to use it, the SpawnEmi�erA�ached function already does that and won’t
crash if it wasn’t assigned a valid particle system.

7 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

Period ‘.’ and Arrow operator ‘->’ (Accessing Variables/


Functions)
Used to access Variables or call Functions of objects. You can type in the period ‘.’ and it
automatically converts to ‘�’ in source editors like Visual Studio when used on a pointer.
While they are similar in use, the ‘.’ is used on Value-types such as structs (like FVector,
FRotator, and FHitResult) and ‘�’ is generally used on classes that you access using
Pointers, like Actor, GameMode, ParticleSystem, etc.

Examples:

// pointer to Actor class called AMyCar ('A' prefix explained later)


AMyCar* MyCar = SpawnActor<AMyCar>(...);
// Calling function on class instance (pointer)
MyCar->StartEngine();
// Getting variable from class instance (pointer)
float Variable = MyCar->EngineTorque;

// struct containing line trace info


FHitResult HitResult;
// FHitResult is a struct, meaning we use it as a value type and not a
class instance.
FVector HitLocation = HitResult.ImpactLocation;

Note: You can use pointers with value types like struct, �oat, etc. You often don’t use
pointers on these types in game code, hence why I used this as the di�erentiator.

Double Colon ‘::’


Used to access ‘static functions’ (and variables) on classes. A good example is
UGameplayStatics, which only consists of static functions, eg. to spawn particles and
sounds. Generally, you’ll have very few static variables, so its main use is for easy-to-
access functions. Static functions cannot be called on a class instance and only on the
class type itself (see below).

Example of calling a static function on a class:

UGameplayStatics::PlaySoundAtLocation(this, SoundOnStagger, GetActorLocation

8 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

Since these functions are static, they don’t belong to a speci�c ‘ UWorld ‘. UWorld is
generally the level/world you play in, but within the editor, it could be many other things
(the static mesh editor has its own UWorld for example). Many things need UWorld ,
and so you will often see the �rst parameter of static functions look like this:

static void PlaySoundAtLocation(const UObject* WorldContextObject, USoundBase* Sound, F

UObject* WorldContextObject can be anything that lives in the relevant world, such
as the character that calls this function. And so most of the time you can pass ‘ this ‘
keyword as the �rst parameter. The ‘const’ keyword in front of the parameter means you
cannot make changes to that WorldContextObject within the context of the function.

You will also see a double colon when declaring the body of a function itself (regardless of
it being ‘static’ or not)

void ASAICharacter::Stagger(UAnimMontage* AnimMontage, FName SectionName /*


= NAME_None*/)
{
// ... code in the function (this is in the .cpp file)
}

Ampersand ‘&’ (References & Address operator)


Also known as the reference symbol and address operator. I �nd that I don’t use this as
often as the others within gameplay code speci�cally, but important to know how to use it
nonetheless as you will need it to pass around functions when se�ing timers or binding
input.

Pass by Reference
A common concept is to ‘pass by reference‘ a value type like a struct, or a big Array �lled
with thousands of objects. If you were to pass these variables into a function, without the
reference symbol, two things happen:

▪ The code creates a copy of the parameter value, in the case of a big array this can be
costly and unnecessary.
▪ More importantly, because a copy is created, you can’t simply change that variable
and have it change in the ‘original’ variable too, you basically cloned it and left the
original variable unchanged. If you want to change the original variable inside the

9 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

function, you need to pass it in as a reference (tthis is speci�c to value types like
�oat, bool, structs such as FVector, etc.) Let me give you an example.

void ChangeTime(float TimeToUpdate)


{
// add 1 second to the total time
TimeToUpdate += 1.0f;
}

Now calling this function as seen in the example below will print out 0.0f at the end since
the original TimeVar was never actually changed.

float TimeVar = 0.0f;

ChangeTime(TimeVar);

print(TimeVar); // This would print out: 0.0f - because we cloned the


original variable, and didn't pass in the original into the function. So
any change made to that value inside the function is lost.

Now we change the function to:

void ChangeTime(float& TimeToUpdate)


{
// add 1 second to the total time
TimeToUpdate += 1.0f;
}

Now if we use the same code as before, we get a di�erent result: The printed value would
now be 1.0f.

float TimeVar = 0.0f;

ChangeTime(TimeVar);

print(TimeVar); // This would print out: 1.0f - because we passed in the


original value by reference, let the function add 1.0f and so it updated
TimeVar instead of a copy.

Address Operator
Another important use is the address operator, which even lets us pass functions as

10 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

parameters into other functions. This is very useful for binding user input and se�ing
timers to trigger speci�c functions.

The BindAxis function in the example below needs to know which function to call when the
mapped input is triggered. We pass in the function and use the address operator (&).

// Called to bind functionality to input


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

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


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

Another common use case is to pass a function into timers. The third parameter is again
the function we pass in to be called when the timer elapses.

// Activate the fuze to explode the bomb after several seconds


GetWorldTimerManager().SetTimer(FuzeTimerHandle, this, &ASBombActor::Explode, MaxFuzeTi

Public, Protected, Private


These keywords can mark variables and functions in the header �le to give ‘access rights’
for other classes and class instances.

Private variables can only be accessed inside that class and not other classes or even
derived classes.

Protected means it cannot be accessed from other classes but can be accessed in the
derived class.

Public means other classes have open access to the variable or function.

Generally, you only want to expose what can be safely called/changed from the outside
(other classes). You don’t want to make your variables public if they should trigger an
event whenever they are changed. Instead, you mark the variable protected or even
private and create a public function instead which sets the variable and calls the desired
event.

11 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

private:
int32 MyInt;

public:
void SetMyInt(int32 NewInt);

Forward Declaring Classes


Forward declaring C++ classes is done in header �les and is done instead of including the
full �les via #include . The purpose of forward declaring is to reduce compile times and
dependencies between classes compared to including the .h �le.

Let’s say we wish to use UParticleSystem class in another header named


MyCharacter.h . The header �le (and compiler) doesn’t need to know everything about
UParticleSystem , just that the word is used as a class.

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "SCharacter.generated.h"
//#include "ParticleSystem.h" // << We don't need to include the entire
file

class UParticleSystem; // << We can instead just 'forward declare' the


type.

UCLASS()
class ACTIONROGUELIKE_API ASCharacter : public ACharacter
{
GENERATED_BODY()

UParticleSystem* CastingEffect;
// ...

The class keyword provides the minimum the compiler requires to understand that
word is in fact a class. If we included the .h �le for the class instead this could negatively
impact our compile times. Any changes to the included header (eg. including your
MyCharacter.h elsewhere in your code) will cause the classes which include said header
to re-compile too.

Here is the character class example that forward declares all the Components used in the
header instead of including their .h �les.

12 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

Forward Declaration is mentioned in Epic’s Coding Standards as well. “If you can use
forward declarations instead of including a header, do so.”

Casting (Cast<T>)
Casting to speci�c classes is something you’ll use all the time. Casting pointers in Unreal
Engine is a bit di�erent from ‘raw C++’ in that it’s safe to cast to types that might not be
valid, your code won’t crash and instead just returns a nullptr (null pointer).

As an example, you might want to Cast your APawn* (pointer) to your own character class
(eg. ASCharacter) as casting is required to access the variables and functions declared in
that speci�c class.

APawn* MyPawn = GetPawn();


ASCharacter* MyCharacter = Cast<ASCharacter>(MyPawn);
if (MyCharacter) // verify the cast succeeded before calling functions
{
// Respawn() is defined in ASCharacter, and doesn't exist in the base
class APawn. Therefore we must first Cast to the appropriate class.
MyCharacter->Respawn();
}

It’s not always preferable to cast to speci�c classes, especially in Blueprint as this can
have a negative impact on how much data needs to be loaded into memory. Any time you
add a Cast to a certain Blueprint class on your EventGraph that object will be loaded into
memory immediately (not when the Cast-node is hit at runtime, but as soon as the
Blueprint itself gets loaded/created), causing a cascade of loaded objects. Especially
when Blueprints reference a lot of assets (meshes, particles, textures) this has a large
impact on your project’s (load/memory) performance.

13 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

Blueprint Example: BlueprintA has a cast-to node in its EventGraph that casts to
BlueprintB. Now as soon as BlueprintA is used/loaded in-game, BlueprintB is loaded at
the same time. They will now both remain in memory even if you don’t actually have
any instances of BlueprintB in your Level.

This often becomes a problem when developers put all their code in the Character
Blueprint. Everything you Cast-to on its EventGraph will be loaded including all their
textures, models, and particles.

Since all C++ classes will be loaded into memory at startup regardless, the main reason to
cast to base classes is compilation time. It will avoid having to recompile classes that
reference (#include) your class headers whenever you make a change. This can have a
cascading e�ect of recompiling classes that depend on each other.

C++ Example: You only cast to AMyCharacter if your function or variable required is
�rst declared in that class. If you instead need something already declared in APawn,
you should simply cast to APawn instead.

One way to reduce class dependencies is through interfaces…so that’s what we will talk
about next.

Interfaces
Interfaces are a great way to add functions to multiple classes without specifying any
actual functionality yet (implementation). Your player might be able to interact with a
large variety of di�erent Actors in the level, each with a di�erent reaction/implementation.
A lever might animate, a door could open or a key gets picked up and added to the
inventory.

Interfaces in Unreal are a bit di�erent from normal programming interfaces in that in
UE you are not required to implement the function, it’s optional.

An alternative to interfaces is to create a single base class (as mentioned earlier) that
contains a Interact() function that child classes can override to implement their own
behavior. Having a single base class is not always ideal or even possible depending on your
class hierarchy, and that’s where interfaces might solve your problem.

14 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

Interfaces are a li�le odd at �rst in C++ as they require two classes with di�erent pre�x
le�ers. They are both used for di�erent reasons but �rst, let’s look at the header.

// This class does not need to be modified.


UINTERFACE(MinimalAPI)
class USGameplayInterface : public UInterface
{
GENERATED_BODY()
};

/**
*
*/
class ACTIONROGUELIKE_API ISGameplayInterface
{
GENERATED_BODY()

// Add interface functions to this class. This is the class that will be
inherited to implement this interface.
public:

UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
void Interact(APawn* InstigatorPawn);
};

With the interface class de�ned you can ‘inherit’ from it in other C++ classes and
implement actual behavior. For this, you use the “I” pre�xed class name. Next to public
AActor we add , public ISGameplayInterface to specify we want to inherit the
functions from the interface.

UCLASS()
class ACTIONROGUELIKE_API ASItemChest : public AActor, public ISGameplayInterface
// 'inherit' from interface
{
GENERATED_BODY()

// declared as _Implementation since we defined the function in interface


as BlueprintNativeEvent
void Interact_Implementation(APawn* InstigatorPawn);
}

BlueprintNativeEvent is useful to allow C++ to provide a base implementation,


Blueprint child classes can then override or extend this function. In C++ the function

15 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

implementation will have an _Implementation su�ix added. This is from code


generated by Unreal.

In order to check whether a speci�c class implements (inherits from) the interface you
can use Implements<T>() . For this, you use the “U” pre�xed class name.

if (MyActor->Implements<USGameplayInterface>())
{
}

Calling interface functions is again unconventional. The signature looks as follows:


IMyInterface::Execute_YourFunctionName(ObjectToCallOn, Params); This is
another case where you use the “I” pre�xed class.

ISGameplayInterface::Execute_Interact(MyActor, MyParam1);

Important: There are other ways to call this function, such as casting your Actor to
the interface type and calling the function directly. However, this fails entirely when
interfaces are added/inherited to your class in Blueprint instead of in C++, so it’s
recommended to just avoid that altogether.

However, if you want to share functionality between Actors but don’t want to use a base
class then you could use an ActorComponent.

Steve Streeting has more details on using Interfaces which I recommend checking out.
There is a code example in the Action Roguelike project as well using SGameplayInterface
used by InteractionComponent to call Interact() on any Actor implementing the
interface.

Delegates (Events)
Delegates (also known as Events) allow code to call one or multiple bound functions when
triggered. Sometimes you’ll see this referred to as Callbacks. For example, It can be
incredibly helpful to bind/listen to a delegate and be noti�ed when a value (such as
character health) changes. This can be a lot more e�icient than polling whether
something changes during Tick() .

16 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

There are several types of these delegates/events. I’ll explain the most commonly used
ones for game code using practical examples rather than low-level language details. I’m
also not covering all the di�erent ways of binding (only focusing on the more practical
ways instead) or niche use cases, you can �nd more details on the o�icial documentation
for those.

Declaring and Using Delegates


You start by declaring the delegate with a MACRO. There are variants available to allow
passing in parameters, these have the following su�ix. _OneParam, _TwoParams,
_ThreeParams, etc. You de�ne these in the header �le, ideally, above the class where you
want to call them.

// These macros will sit at the top of your header files.


DECLARE_DYNAMIC_MULTICAST_DELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams()

We’ll start by showing the process of declaring and using delegates in detail with a
commonly used type, and then explain the other types more brie�y as they share the
same concepts.

Multicast Dynamic
One of the most used types of delegate in your game code as they can be exposed to
Blueprint to bind and receive callbacks.

Note: Dynamic Multicast Delegates are also known as Event Dispatchers in Blueprint.

The macros take at least one parameter, which de�nes their name. eg.
FOnA�ributeChanged could be a name we use as our Delegate to execute whenever an
a�ribute such as Health changes.

DECLARE_DYNAMIC_MULTICAST_DELEGATE(<typename>)
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(<typename>, <paramtype1>, <paramvarname1>,

Here is one example of a delegate with four parameters to notify code about a change to
an a�ribute. The type and variable names are split by commas, unlike normal functions.

17 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

DECLARE_DYNAMIC_MULTICAST_DELEGATE_FourParams(FOnAttributeChanged, AActor, InstigatorAc

You now add the delegate in your class header, which may look as follows:

UPROPERTY(BlueprintAssignable, Category = "Attributes")


FOnAttributeChanged OnHealthChanged;

You may have noticed BlueprintAssignable, this is a powerful feature of the Dynamic
delegates which can be exposed to Blueprint and used on the EventGraph.

Executing Delegates
Finally, to actually trigger the callback we call OnHealthChanged.Broadcast() and pass in
the expected parameters.

OnHealthChanged.Broadcast(InstigatorActor, this, NewHealth, Delta);

Binding to Delegates

Binding in C++

You should *never* bind your delegates in the constructor and choose either
AActor::PostInitializeComponents() or BeginPlay() to avoid issues where
delegates get serialized into the Blueprint and will still be called even when you later
remove the delegate binding in C++.

Since delegates are weakly referenced you often don’t need to unbind delegates when
destroying objects/actors unless you want to manually stop listening/reacting to speci�c
events.

You can bind to a delegate calling .AddDynamic() . The �rst parameter takes a
UObject for which we can pass ‘ this ‘. The second parameter types the address of the
function ( YourClass::YourFunction ) which is why we pass the function with the
ampersand ( & ) symbol which is the address operator.

void ASAICharacter::PostInitializeComponents()
{

18 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

Super::PostInitializeComponents();

AttributeComp->OnHealthChanged.AddDynamic(this, &ASAICharacter::OnHealthChanged);
}

The above OnHealthChanged function is declared with UFUNCTION() in the header.

UFUNCTION()
void OnHealthChanged(AActor* InstigatorActor, USAttributeComponent* OwningComp,

Binding in Blueprint

You can easily bind your dynamic delegates in Blueprint. When implemented on an
ActorComponent as in the example below you can select the Component in the outliner
and click the “+” symbol in its details panel. This creates the Delegate on the EventGraph
and is already bound for us.

You can also manually bind the delegates via the EventGraph (eg. binding to another
Actor’s delegates.

19 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

Note: Dynamic delegates are less performant than non-dynamic (seen below)
variants. It’s therefore advisable to only use this type when you want to expose it to
Blueprint.

C++ Delegates
Macro: DECLARE_DELEGATE , DECLARE_DELEGATE_OneParam

When used only in C++ we can de�ne delegates with an unspeci�ed amount of
parameters. In the following example, we’ll use a more complex use case which is
asynchronously loading game assets.

The StreamableManager of Unreal de�nes a FStreamableDelegate .

DECLARE_DELEGATE(FStreamableDelegate);

This doesn’t specify any parameters yet and lets us de�ne what we wish to pass along in
our own game code.

The following is taken from SGameModeBase in the ActionRoguelike project (link to code).
We asynchronously load the data of an enemy Blueprint to spawn them once the load has
�nished.

20 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

if (UAssetManager* Manager = UAssetManager::GetIfValid())


{
// Primary Id is part of AssetManager, we grab one from a DataTable
FPrimaryAssetId MonsterId = SelectedMonsterRow->MonsterId;

TArray<FName> Bundles;

// A very different syntax, we create a delegate via CreateUObject and


pass in the parameters we want to use once loading has completed several
frames or seconds later. (In this case the MonsterId is the asset we are
loading via LoadPrimaryAsset and Locations[0] is the desired spawn location
once loaded)
FStreamableDelegate Delegate = FStreamableDelegate::CreateUObject(this, &ASGameModeBa

// Requests the load in Asset Manager on the MonsterId (first param) and
passes in the Delegate we just created
Manager->LoadPrimaryAsset(MonsterId, Bundles, Delegate);
}

In the example above we create a new Delegate variable and �ll it with variables, in this
case MonsterId and the �rst vector location from an array ( Locations[0] ). Once the
LoadPrimaryAsset function from Unreal has �nished, it will call the delegate
OnMonsterLoaded with the provided parameters we passed into the CreateUObject
function previously.

void ASGameModeBase::OnMonsterLoaded(FPrimaryAssetId LoadedId, FVector SpawnLocation)

Another example of using delegates/callbacks is with Timers. We don’t need to specify our
own delegate �rst and can directly pass in the function address so long as it has no
parameters. It’s possible to use timers with parameters as well. To learn more you can
check out my blog post on Using C++ Timers.

There is a lot more to talk about, but this should provide a core understanding from which
to build. There are many more variants to the macros and di�erent ways to bind…which
could be a whole article on its own.

To read more about delegates I recommend BenUI’s Intro to Delegates and Advanced
Delegates in C++.

Public/Private Folders

21 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

Public and private folders de�ne which �les are available to use in other modules.
Generally, your header �les are placed in the Public folder so other modules can gain
access and the cpp �les are in the Private folder. Headers that are not meant to be used
directly by other modules can go into the Private folder as well.

Your primary game module doesn’t need this public/private structure if you don’t intend to
have other modules depend on it.

I recommend checking out Ari’s talk on modules for more information on Modules and how
to use them.

Class Prefixes (F, A, U, E, G, T, …)


Classes in Unreal have a pre�x, for example, the class ‘Actor’ is named ‘AActor’ when seen
in C++. These are helpful in telling you more about the type of object. Here are a few
important examples.

A. Actor derived classes (including Actor itself) have A as pre�x, eg. APawn, AGameMode,
AYourActorClass

U. UObject derived classes, including UBlueprintFunctionLibrary ,


UActorComponent and UGameplayStatics . Yes, AActor derives from UObject , but
it overrides it with its own A pre�x.

F. Structs, like FHitResult, FVector, FRotator, and your own structs should start with F.

E. The convention for enum types. ( EEnvQueryStatus , EConstraintType , …)

G. “globals” for example, GEngine->AddOnscreenDebugMessage() where GEngine is


global and can be accessed anywhere. Not very common in your use within gameplay
programming itself though.

T. Template classes, like TSubclassOf<T> (class derived from T, which can be almost
anything), TArray<T> (lists), TMap<T> (dictionaries) etc. classes that can accept
multiple classes. Examples:

// A list of strings.
TArray<FString> MyStrings;

// A list of actors

22 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

TArray<AActor*> MyActors;

// Can be assigned with a CLASS (not an instance of an actor) that is


either a GameMode class or derived from GameMode.
TSubclassOf<AGameMode> SubclassOfActor;

Mike Fricker (Lead Technical Director) explained the origins of “F” Pre�x:

“The ‘F’ pre�x actually stands for “Float” (as in Floating Point.)“

“Tim Sweeney wrote the original “FVector” class along with many of the original math
classes, and the ‘F’ pre�x was useful to distinguish from math constructs that would
support either integers or doubles, even before such classes were wri�en. Much of
the engine code dealt with �oating-point values, so the pa�ern spread quickly to
other new engine classes at the time, then eventually became standard everywhere.”

“This was in the mid-nineties sometime. Even though most of Unreal Engine has been
rewri�en a few times over since then, some of the original math classes still resemble
their Unreal 1 counterparts, and certain idioms remain part of Epic’s coding standard
today.”

Project Prefixes
Projects in Unreal should use their own (unique) pre�x to signify their origin. For example,
all classes in Unreal Tournament use “UT” ( AUTActor , UUTAbility ), and Fortnite uses
“Fort” pre�x ( AFortActor , UFortAbility , etc).

In the many code examples in this guide, I used “S” as the pre�x. These examples are from
the Action Roguelike project. (Note: Since Unreal’s Widgets/Slate already uses “S” as a
pre�x one could argue I should have used “SU” or some other more unique pre�x – in all
these years I’ve never had any issue with this – so it’s been more of a cosmetic issue).

Common Engine Types


Besides the standard types like float , int32 , bool , which I won’t cover as there is
nothing too special to them within Unreal Engine – Unreal has built-in classes to handle
very common logic that you will use a lot throughout your programming. Here are a few of
the most commonly seen types from Unreal that you will use. Luckily the o�icial

23 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

documentation has some information on these types, so I will be referring to that a lot.

Ints are special in that you are not supposed to use “int” in serialized UProperties as
the size of int can change per platform. That’s why Unreal uses its own sized int16,
int32, uint16, etc. – Source

FString, FName, FText


There are three types of ‘strings’ in Unreal Engine that are used for distinctly di�erent
things. It’s important to select the right type for the job or you’ll su�er later. The most
common problem is using FString for UI text instead of FText , this will be a huge
headache later if you plan to do any sort of localization.

FString, The base representation for strings in Unreal Engine. Used often when debugging
and logging information or passing raw string information between systems (such as REST
APIs). Can be easily manipulated.

FName, Essentially hashed strings that allow to much faster comparisons between two
FNames. �FNames don’t change once created) and are used often for look-ups such as
SocketNames on a Skeletal Mesh and GameplayTags.

FText, Front-end text to display to the user. Can be localized easily. All your front-facing
text should always be FText instead of FNames or FString.

Here is a piece of Documentation on String handling including how to convert between


the di�erent types.

FVector, FRotator, FTransform �FQuat)


Used to specify the location, rotation, and scale of things in the World. A line trace for
example needs two FVectors (Locations) to specify the start and end of the line. Every
Actor has an FTransform that contains Location, Rotation, and Scale to give it a place in
the world.

FVector, 3-axis as XYZ where Z is up. speci�es either a Location or a direction much like
common Vector-math.

FRotator, 3 params Pitch, Yaw and Roll to give it a rotation value.

24 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

FTransform, consists of FVector (Location), FRotator (Rotation) and FVector (Scale in 3-


axis).

FQuat, another variable that can specify a rotation also known by its full name as
Quaternion, you will mostly use FRotator in game-code however, FQuat is less used
outside the engine modules although it can prevent Gimbal lock. (It’s also not exposed to
Blueprint)

TArray, TMap, TSet


Basically variations of lists of objects/values. Array is a simple list that you can add/remove
items to and from. TMaps are dictionaries, meaning they have Keys and Values (where the
Key must always be unique) eg. TMap<int32, Actor> where a bunch of Actors are mapped
to unique integers. And �nally, TSet which is an optimized (hashed) version of TArray,
requires items in the list to be unique. Can be great for certain performance scenarios, but
typically you would use TArray, unless you �nd you need to squeeze performance out of a
speci�c piece of code.

▪ Arrays in Unreal Engine.


▪ TMaps (aka Dictionaries)
▪ TSet

TSubclassOf<T>
Very useful for assigning classes that derive from a certain type. For example, you may
expose this variable to Blueprint where a designer can assign which projectile class must
be spawned.

UPROPERTY(EditAnywhere) // Expose to Blueprint


TSubclassOf<AProjectileActor> ProjectileClass; // The class to assign in
Blueprint, eg. BP_MyMagicProjectile.

Now the designer will get a list of classes to assign that derive from ProjectileActor,
making the code very dynamic and easy to change from Blueprint.

Here we use the TSubclassOf variable ProjectileClass to spawn a new instance: (link to
code)

FTransform SpawnTM = FTransform(ProjRotation, HandLocation);

25 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

GetWorld()->SpawnActor<AActor>(ProjectileClass, SpawnTM, SpawnParams);

▪ Documentation on TSubclassOf

C++ MACROS (& Unreal Property System)


The ALL CAPS preprocessor directives are used by the compiler to ‘unfold’ into (large)
pieces of code. In Unreal Engine, it’s most often used by the Unreal Property System and
to add boilerplate code to our class headers. These examples are all macros, but Macros
can be used for a lot more than shown below.

UFUNCTION()
Allows extra markup on functions, and exposes it to the Property System (Re�ection) of
Unreal. Commonly used to expose functions to Blueprint. Sometimes required by the
engine to bind functions to delegates (eg. binding a timer to call a function).

Here is additional information in a blog post on the available keywords within


UFUNCTION() and how to use them. There are a lot of function speci�ers worth checking
out, and BenUI does a great job of detailing what’s available.

// Can be called by Blueprint


UFUNCTION(BlueprintCallable, Category = "Action")
bool IsRunning() const;

// Can be overriden by Blueprint to override/extend behavior but cannot be


called by Blueprint (only C++)
UFUNCTION(BlueprintNativeEvent, Category = "Action")
void StartAction(AActor* Instigator);

UPROPERTY()
Allows marking-up variables, and exposing them to the Property System (Re�ection) of
Unreal. Commonly used to expose your C++ to Blueprint but it can do a lot more using this
large list of property speci�ers. Again, it’s worth checking out BenUI’s article on
UPROPERTY speci�ers.

// Expose to Blueprint and allow editing of its defaults and only grant
read-only access in the node graphs.

26 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI")


TSoftObjectPtr<UTexture2D> Icon;

// Mark 'replicated' to be synchronized between client and server in


multiplayer.
UPROPERTY(Replicated)
USActionComponent* ActionComp;

GENERATED_BODY()
At the top of classes and structs and used by Unreal to add boilerplate code required by
the engine.

GENERATED_BODY()

USTRUCT, UCLASS, UENUM


These macros are required when de�ning new classes, structs, and enums in Unreal
Engine. When you create your new class, this is already added for you in the Header. By
default, they will be empty like UCLASS() but can be used to add additional markup to an
object for example

USTRUCT(BlueprintType)
struct FMyStruct
{
}

UE_LOG (Logging)
Macro to easily log information including a category (eg. LogAI, LogGame, LogEngine) and
a severity (eg. Log, Warning, Error, or Verbose) and can be an incredibly valuable tool to
verify your code by printing out some data while playing your game much like PrintString in
Blueprint.

// The simple logging without additional info about the context


UE_LOG(LogAI, Log, TEXT("Just a simple log print"));
// Putting actual data and numbers here is a lot more useful though!
UE_LOG(LogAI, Warning, TEXT("X went wrong in Actor %s"), *GetName());

27 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

The above syntax may look a bit scary. The third parameter is a string we can �ll with
useful data, in the above case we print the name of the object so we know in which
instance this happened. The asterisk (*) before GetName() is used to convert the return
value to the correct type (from FString returned by the function to Char[] for the macro).
The Unreal Wiki has a lot more detailed explanation on logging.

Modules
Unreal Engine consists of a large number �1000+) of individual modules. Your game code is
contained in one or multiple modules. You can place your game-speci�c logic in one
module, and your more generic framework logic for multiple games in another to keep a
separation of dependencies.

You can �nd examples of these code modules in your engine installation folder (eg. Epic
Games\UE_5.0\Engine\Source\Runtime\AIModule) where each module has its own
[YourModuleName].build.cs �le to con�gure itself and its dependencies.

Not every module is loaded by default. When programming in C++ you sometimes need to
include additional modules to access their code. One such example is AIModule that you
must add to the module’s *.build.cs �le in which you wish to use it before being able to
access any of the AI classes it contains.

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine"

The above is one example from ActionRoguelike.build.cs where AIModule (among


several others) has been added.

You can include additional modules through the .uproject as well instead of the build �le.
This is where the editor will automatically add modules under
AdditionalDependencies when required (such as the moment of creating a new C++
class that derives from a missing module).

Ari from Epic Games has a great talk on Modules that I recommend checking out and is
linked below. I’ve added a few takeaways from his talk.

Why use modules?


▪ Be�er code practices/encapsulation of functionality

28 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

▪ Re-use code easily between projects


▪ Only ship modules you use (eg. trim out Editor-only functionality and unused Unreal
features)
▪ Faster compilation and linking times
▪ Be�er control of what gets loaded and when.

Garbage Collection (Memory Management)


Unreal Engine has a built-in garbage collection that greatly reduces our need to manually
manage object lifetime. You’ll still need to take some steps to ensure this goes smoothly,
but it’s easier than you’d think. Garbage collection occurs every 60 seconds by default and
will clean up all unreferenced objects.

When calling MyActor->DestroyActor() , the Actor will be removed from the world and

29 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

prepared to be cleared from memory. To properly manage ‘reference counting’ and


memory you should add UPROPERTY() to pointers in your C++. I’ll discuss that more in
the section below.

It may take some time before GC kicks in and actually deletes the memory/object. You
may run into this when using UMG and GetAllWidgetsOfClass . When removing a
Widget from the Viewport, it will remain in memory and is still returned by that
function until GC kicks in and has veri�ed all references are cleared.

It’s important to be mindful of how many objects you are creating and deleting at runtime
as Garbage Collection can easily eat up a large chunk of your frame time and cause
stu�ering during gameplay. There are concepts such as Object Pooling to consider.

Automatic Updating of References (Actors &


ActorComponents)
References to Actors (and ActorComponents) can be automatically nulled after they get
destroyed. For this to work you must mark the pointer with UPROPERTY() so it can be
tracked properly.

// SInteractionComponent.h
UPROPERTY()
TObjectPtr<AActor> FocusedActor;

“Destroyed actors don’t have references to them nulled until they’re actually garbage
collected. That’s what IsValid(<yourobject>) is used for checking.” – Ari Arnbjörnsson

You can read more about automatic updating of references on the o�icial docs. The thing
to keep in mind is that it only works for Actor and ActorComponent derived classes.

In UE5 the behavior for automatically clearing RawPtrs / ObjectPtrs will change.

“This will be changing a bit in UE5. The GC will no longer clear UPROPERTY + RawPtr/
TObjectPtr references (even for Actors) but instead mark them as garbage
(MarkAsGarbage()) and not GC them. The only way to clear the memory will be to null
the reference or use weak pointers.” – Ari Arnbjörnsson

30 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

I will update this post once the new behavior has been enabled by default.

TWeakObjPtr<T> �UObjects)
Weak Object Pointer. This is similar to pointers like UObject* , except that we tell the
engine that we don’t want to hold onto the memory or object if we are the last piece of
code referencing it. UObjects are automatically destroyed and garbage collected when no
code is holding a (hard) reference to it. Use weak object pointers carefully to ensure
objects are GC’ed when needed.

// UGameAbility derived from UObject


TWeakObjectPtr<UGameAbility> MyReferencedAbility;

Now we don’t try to hold onto the object explicitly and it can be garbage collected safely.
Before accessing the object, we must call .Get() which will a�empt to retrieve the
object from the internal object array and makes sure it’s valid. If it’s no longer a valid
object, a nullptr is returned instead.

UGameAbility* Ability = MyReferencedAbility.Get();


if (Ability)
{
}

▪ Documentation on WeakObjPtr<T>
▪ Soft & Weak Object Pointers (Ari Arnbjörnsson)
▪ Even more technical, on Smart Pointers in Unreal

Class Default Object


Class Default Object is the default instance of a class in Unreal Engine. This instance is
automatically created and used to quickly instantiate new instances. You can use this
CDO in other ways too to avoid having to manually create and maintain an instance.

You can easily get the CDO in C++ via GetDefault<T>. You should take care to not
accidentally make changes to the CDO as this will bleed over into any new instance
created for that class.

31 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

Below is one example from SaveGameSubsystem using the ‘class default object’ to access
DeveloperSe�ings (Project & Editor Se�ings) without creating a new instance.

// Example from: SSaveGameSubsystem.cpp (in Initialize())

const USSaveGameSettings* Settings = GetDefault<USSaveGameSettings>();

// Access default value from class


CurrentSlotName = Settings->SaveSlotName;

Asserts (Debugging)
If you really need to be sure if something is not Null or a speci�c (if-)statement is true and
want the code to tell you if it isn’t, then you can use Asserts. Asserts are great as
additional checks in code where if it were to silently fail, code later down the line may fail
too (which may then take a while to debug and �nd the origin).

Two main assertion types are check and ensure.

check(MyValue == 1); // treated as fatal error if statement is 'false'


check(MyActorPointer);

// convenient to break here when the pointer is nullptr we should


investigate immediately
if (ensure(MyActorPointer)) // non-fatal, execution is allowed to continue,
useful to encapsulate in if-statements
{
}

Ensure is great for non-fatal errors and is only triggered once per session. You can use
ensureAlways to allow the assert to trigger multiple times per session. But make sure
the assert isn’t in a high-frequency code path for your own sake or you’ll be �ooded with
error reports.

It’s good to know that Asserts are compiled out of shipping builds by default and so it
won’t negatively a�ect runtime performance for your end-user.

By adding these asserts you are immediately noti�ed of the (coding) error. One tip I would
give here is to only use it for potential coder mistakes and perhaps don’t use it when a

32 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

piece of content isn’t assigned by a designer (having them run into asserts isn’t as useful
as to them it will look like a crash (unless they have an IDE a�ached) or stall the editor for a
bit (as a minidump is created) and not provide a valuable piece of information). For them
might be be�er of using logs and prints on the screen to tell them what they did not set up
properly. I sometimes still add in asserts for content mistakes as this is very useful in solo
or small team projects.

Core Redirects
Core Redirects are a refactoring tool. They let you redirect pre�y much any class,
function, name, etc. after your C++ has changed via the con�guration �les (.ini). This can
be incredibly helpful in reducing the massive headache of updating your Blueprints after a
C++ change.

The o�icial documentation (above) does a pre�y good job of explaining how to set this up.
It’s one of those things that’s good to know before you need it. Modern IDEs with proper
Unreal Engine support such as JetBrains Rider even have support for creating redirects
when you refactor your Blueprint exposed code.

Closing
I hope this article provided you with some new insight into C++ and how it’s used in Unreal
Engine.

Please comment below if you’d like to see anything else you struggled with when starting
with C++ and gameplay programming in Unreal Engine so I can add it to the list! This article
is mainly focused on the uncommon aspects that are unique to Unreal Engine and how
they apply within that context rather than C++ or programming in general.

W h y s to p h e r e ? D i ve d e e p e r i n to t h e wo r l d o f C + + a n d U n r e a l E n g i n e w i t h my
i m m e rs i ve c o u rs e ! G ra b yo u r l i m i te d - t i m e 2 0 % d i s c o u n t a n d s t a r t l e a r n i n g n o w !

As always, don’t forget to follow me on Twi�er for more Unreal Engine tutorials!

On The Horizon…

33 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

Things that didn’t quite make it in yet or require a more detailed explanation in the current
sections. Leave your suggestions in the comments!

▪ Unreal Header Tool / Unreal Build Tool (”Unreal Build System”)


▪ Project Structure (Game, Engine, build.cs, Target, binaries, .uproject)
▪ Including other classes (and how to �nd their path)
▪ Hot Reloading & Live Coding in UE5.0
▪ IDE recommendations and setup
▪ Timers, Async actions (Latent), Multi-threading
▪ Game Class Hierarchy and most commonly used classes (primer).
▪ virtual/override keywords. (”Virtual Functions and Polymorphism”)
▪ ‘const’ keyword & const correctness
▪ Operator Overloading (examples of where Unreal has done so, eg. with FString when
used with logging)

References & Further Reading


▪ Laura’s C++ Speedrun
▪ Why C++ In Unreal Engine Isn’t That Scary?
▪ Gameplay Framework Primer
▪ Introduction to Unreal C++ Programming (External)
▪ Gameplay Framework Documentation (External)
▪ Gameplay Programming Documentation (External)

Sign Up for Unreal Engine Content


Receive the latest tutorials, tricks, hidden gems and more exclusive content!

Email

Subscribe

Categories: C++ Tutorials Unreal Engine

34 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

Tags: C++ Tutorial UE4 UE5 Unreal Engine

11 Responses

 C o m m en t s 1 1  P i n g b a c ks 0

Massca d
April 15, 2023 at 4:17 PM

Thank you so much!

Reply

J a ke
February 27, 2023 at 5:05 PM

Wonderful post Tom. De�nitely like it and will be dishing it out. For some quick
feedback, I think it is worth mentioning that for the C++ only delegates, you don’t
need to do the macro at all. You can just use
“TDelegate({ReturnType>(Parameters)>” or “TMulticastDelegate”.

This can help reduce macro noise, plus you don’t have to come up with a signature
name, can just use it in-line. “TMulticastDelegate SomethingHappened;” – as an
example

Reply

J a ke
February 27, 2023 at 5:08 PM

Just want to highlight that for whatever reason, the post didn’t take all of my
characters. So some of it looks weird. Mostly the angled brackets. Let me try
again: TDelegate and TMulticastDelegate

Reply

35 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

Tom Looman 
February 27, 2023 at 6:13 PM

Interesting! Thank you for contributing Jake, I’ll look into this and see if it can be
included.

Reply

Kyle Cuss
February 16, 2023 at 1:00 AM

Thank you for this post. I just started you course recently and had found some of C++
syntax confusing coming from a mostly C# background. This is helped clear up a lot
things and will be a good reference to keep coming back to as I learn more.

Reply

C h o p i n D ev
February 15, 2023 at 2:49 AM

“if (ensure(MyActorPointer)”
missing the right bracket �

Reply

Tom Looman 
February 15, 2023 at 11:30 AM

Thanks, Fixed!

Reply

A r t i c l e C o m m e n te r
February 15, 2023 at 2:07 AM

36 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

It would be helpful to get a de�nitive answer on what SDKs we actually need installed
to even create a C++ project in the �rst place. I’ve installed all the prerequisites
(through VSCode), but still can’t even create a new project with C++ support even
though I have all the listed requirements, and they are listed in the engine itself as
being found. There are always vague missing dependency errors, and no real answers
on the forums or documentation. It often seems like they don’t know for sure
themselves. It’s tiresome doing countless SDK installs and still not making any
progress to solving the problem.

Reply

Tom Looman 
February 15, 2023 at 11:32 AM

I agree! This has always been a pain. The error messages for this are often not
helpful enough. I’ll see what I can do for the “IDE recommendations & setup”
section.

Reply

B en Z e i g l e r
February 14, 2023 at 8:17 PM

Hey Tom, good intro article! Here are some notes I took:

As this is a new doc I would think most people reading this will be using UE5, so you
probably want to mention TObjectPtr and maybe adjust the examples. Current best
practice is to always use TObjectPtr in UPROPERTY de�nitions but not in C++ code.

The AMyCar* MyCar example makes me nervous because as wri�en it’s a clear invalid
memory access, maybe you can format it so it’s more clear there’s implied code
missing there?

For the delegate section, you may want to mention that dynamic multicast is also
called event dispatcher in the BP editor. Might also be worth explaining the single/vs
multicast di�erence more as the current text kind of reads like dynamic is always
multicast and C++ is always single.

37 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/

On a format note, the longer comments are kind of awkward because the CSS you’re
using gives a hard to see scrollbar in those sections. The article would be easier to
read on desktop if it was wider as it’s only using 30% of my screen on 1080p.

Reply

Tom Looman 
February 14, 2023 at 8:26 PM

Fantastic feedback Ben, exactly what I was looking for. I’ll update the article to
re�ect all these suggestions as these are all perfect.

Reply

Leave a comment on this post!

38 of 38 19/03/2024, 23:30

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy