Unreal Engine C++ Complete Guide - Tom Looman
Unreal Engine C++ Complete Guide - Tom Looman
com/unreal-engine-cpp-guide/
Tom Looman
Home > C++ / Tutorials / Unreal Engine
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.
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 !
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.
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.
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;
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;
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/
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/
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:
7 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/
Examples:
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.
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:
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)
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.
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.
ChangeTime(TimeVar);
Now if we use the same code as before, we get a di�erent result: The printed value would
now be 1.0f.
ChangeTime(TimeVar);
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 (&).
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.
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);
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "SCharacter.generated.h"
//#include "ParticleSystem.h" // << We don't need to include the entire
file
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.
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.
/**
*
*/
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()
15 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/
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>())
{
}
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.
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/
You now add the delegate in your class header, which may look as follows:
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.
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);
}
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.
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/
TArray<FName> Bundles;
// 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.
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.
A. Actor derived classes (including Actor itself) have A as pre�x, eg. APawn, AGameMode,
AYourActorClass
F. Structs, like FHitResult, FVector, FRotator, and your own structs should start with F.
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;
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).
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, 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.
FVector, 3-axis as XYZ where Z is up. speci�es either a Location or a direction much like
common Vector-math.
24 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/
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)
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.
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)
25 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/
▪ Documentation on TSubclassOf
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).
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/
GENERATED_BODY()
At the top of classes and structs and used by Unreal to add boilerplate code required by
the engine.
GENERATED_BODY()
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.
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.
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.
28 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/
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/
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.
// 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.
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.
▪ Documentation on WeakObjPtr<T>
▪ Soft & Weak Object Pointers (Ari Arnbjörnsson)
▪ Even more technical, on Smart Pointers in Unreal
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.
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).
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!
Subscribe
34 of 38 19/03/2024, 23:30
Unreal Engine C++ Complete Guide - Tom Looman https://www.tomlooman.com/unreal-engine-cpp-guide/
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
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
38 of 38 19/03/2024, 23:30