Skip to content

C++ Programming

C++ Programming in Unreal Engine 5 is rather different from standard C++ programming. The engine comes with a few quirks and nuances that you need to be aware of. This manual will guide you through the fundamentals of C++ programming in Unreal Engine 5.

Development Setup

Installing a compatible C++ compiler is the first step to getting started with C++ development in Unreal Engine. Unreal Engine 5 requires a minimum language version of C++17 to build.

Windows

Microsoft Visual Studio is the recommended IDE for C++ development in Unreal Engine 5 on Windows. The engine requires a minimum version of Visual Studio 2022 to build, since v5.4. You can download Visual Studio Community for free from the official website.

During installation, make sure to select the following workloads and the specified components:

Visual Studio Installer

You will also need the .Net Framework SDK, which the editor will have you install when you create your first C++ project.

Rider IDE

The Visual Studio suite comes with its own IDE, which is arguably not the best choice for Unreal Engine development. Instead, we recommend using JetBrains Rider, which is a cross-platform C++ IDE that is specifically designed for game development. Unlike Visual Studio, Rider is not free, but it is well worth the price.

If you decide to go with JetBrains Rider, get the IDE and install it. You must need to navigate to General > Source Code in Editor Preferences and set the Source Code Editor to Rider so that the editor will open the IDE when you open a C++ file.

Rider as Source Code Editor

Once you have Rider installed, you must open up the project in Rider. You can do so by opening the .uproject file in Rider. You may be prompted to install the RiderLink Plugin, which improves the integration between Rider and Unreal Engine. You can choose to install it to either the Game project alone or to the Engine itself.

Rider Link Installation Prompt

Now that you have Rider set up, you can open up the editor from Rider by running or debugging the project. You need to select Editor as the Build Target when you run or debug the project. For more info on the available options, see Build System.

Rider: Run / Debug

You can still open up the project in the editor just like before, but this can lead to some issues with the build process, especially if you intend to use Live Coding.

Linux

Incomplete

This section is incomplete and needs to be expanded.

MacOS

Incomplete

This section is incomplete and needs to be expanded.

Architecture

In an Unreal Engine project, the source code is organized into modules, individual units of code that can be compiled separately. Each module is structured as a directory within the Source folder of the project, with a .Build.cs file at its root:

<ModuleName>
 ├── Public # (1)!
   ├── <ModuleName>.h
   └── *.h 
 ├── Private # (2)!
   ├── <ModuleName>.cpp
   ├── *.cpp 
   └── *.h
 └── <ModuleName>.Build.cs # (3)!
  1. The Public directory contains the module's public .h files, which are accessible to other modules.
  2. The Private directory contains the module's private .h files and .cpp files, which won't be exposed to other modules.
  3. Defines the build settings for the module.

The .Build.cs file is a C# script that defines the module's build settings. Among other things, the script specifies the module's dependencies, which are other modules that the current module depends on, i.e., modules with header files that the current module #includes.

using UnrealBuildTool;

public class ModuleName : ModuleRules {
    public ModuleName(ReadOnlyTargetRules Target) : base(Target) {
        PublicDependencyModuleNames/*(1)!*/.AddRange( 
            new string[] { 
                "Core",
                "Engine",
            }
        );
        PrivateDependencyModuleNames/*(2)!*/.AddRange( 
            new string[] {
                "Landscape",
            }
        );
    }
}
  1. To #include a header file from another module in the Public .h files, you need to add the module's name to this array.

    It is recommended to avoid bloating the Public .h files with unnecessary imports and defer them via forward declarations.

  2. To #include a header file from another module in the Private .h/.cpp files, you need to add the module's name to this array.

Another key ingredient of a module is an implementation of the IModuleInterface, declared in the <ModuleName>.h file. The interface comes with a few lifecycle hooks that you can override to perform custom initialization and cleanup logic. The implementation has to be registered with the engine using the IMPLEMENT_GAME_MODULE macro in the <ModuleName>.cpp file:

ModuleName.cpp
IMPLEMENT_GAME_MODULE/*(1)!*/(FModuleName, ModuleName);
  1. The first argument is the name of the module's implementation class, and the second argument is the name of the module.

When you create a C++ project, UE automatically generates a module with the same name within the Source directory. This module is the primary gameplay module of the project. To distinguish it from other modules, it is registered using IMPLEMENT_PRIMARY_GAME_MODULE, rather than IMPLEMENT_GAME_MODULE as shown in the example above.

Note

Your modules don't necessarily have to be at the root of the Source directory. You can organize them into subfolders as you see fit. The organization of the engine's modules is a good example of this.

The .uproject file at the root of your project associates a type and a loading phase with every module in your project. The type of the module specifies which build targets should include the module, while the loading phase determines when the module should be loaded if it is included.

ProjectName.uproject
{
    "FileVersion": 3,/*(1)!*/
    "EngineAssociation": "5.4",/*(2)!*/
    "Category": "",
    "Description": "",
    "Modules": [
        {
            "Name": "ProjectName"/*(3)!*/,  
            "Type": "Runtime"/*(4)!*/,
            "LoadingPhase": "Default"/*(5)!*/
        },
        { ... }
    ],
    "Plugins": [ ... ]
}
  1. See EProjectDescriptorVersion for more info.
  2. The engine version that the project is associated with.
  3. This is the primary game module of the project, and so, it has the same name as the project.
  4. Most common choices are Runtime (to always include the module) and Editor (to only include the module when loading the editor). See EModuleType for more info.
  5. In most cases, Default will do. See ELoadingPhase for more.

Plugins

Incomplete

This section is incomplete and needs to be expanded.

Build System

Unreal Build Tool is Unreal Engine's build system. UBT will build up a dependency graph of your modules, before compiling and linking them into an executable binary. When you want to build your project, you need to specify the build target and the build state.

The build target specifies which modules should be included in the build. Targets are defined as .Target.cs files in Source. Every new project comes with two build targets out of the box:

  • Game: Includes all the runtime modules needed to boot up the game.
  • Editor: Includes whatever it takes to boot up the game and the editor.

The build state, on the other hand, specifies how the project should be built. There are three primary choices in a typical Unreal Engine project:

  • Debug Game: Builds everything without any optimizations, allowing you to debug the game modules (but not the engine modules).
  • Development: Builds the modules with most optimizations methods enabled. This is the default build state in the editor.
  • Shipping: Builds the modules with all optimizations enabled and strips away everything unnecessary for booting up the game.

In Rider, you can choose the build target and build state from the Solution Configurations menu.

Note

If you build the engine from source, an alternative build state will be introduced which is simply called Debug. This build state will allow you to debug the engine modules as well. Moreover, there will be two more build targets named Client and Server. These targets are used to build the client and server executables separately.

Live Coding

Live Coding allows you to make changes to your C++ code and patch them into the running game without having to restart the editor. You simply need to trigger the process from the editor:

Live Coding Compile Button

Note that the process may fail to patch the changes if the changes are too drastic. This is often the case when object reinstancing is triggered due to drastic changes in the classes or changes to the defaults in the header files. In such cases, you will need to close up the editor and rebuild the project from the IDE to apply the changes.

C++ Nuances

Unreal Engine takes C++ and adds its own twist to it. In addition to everything you can do with standard C++, Unreal Engine offers a few handy additions, including alternatives to the C++ standard library, managed objects, and a few other useful features.

Primitives

In Unreal Engine, your standard boolean (bool) and floating-point types (float and double) are available. However, Epic recommends substituting the standard integer types with their own, which are guaranteed to have a specific size across platforms.

Size Unsigned Signed
8-bit uint8 int8
16-bit uint16 int16
32-bit uint32 int32
64-bit uint64 int64

Type Names

Epic recommends using PascalCase for pretty much everything, such as your classes, methods, variables, etc. To distinguish type names from instances, Epic suggests using a set of prefixes for the type names. Epic's recommended prefixes are:

  • U: UObject subclasses.
  • A: AActor subclasses.
  • I: Interfaces.
  • E: Enums.
  • T: Templates.
  • S: Slate Widgets.
  • F: Structs, and classes that are not subclasses of UObject or AActor.

There is also a rather peculiar convention for boolean variables. Boolean variables are prefixed with a lowercase b, but no other primitive types get the same treatment.

Finally, Epic also recommends using a short prefix specific to your project / plugin. For example, they use Fort for Fortnite, with names like AFortCharacter, UFortHealthComp, etc.

Standard Library

Unreal Engine offers alternatives to many elements of the C++ standard library, which are optimized for performance and memory1. These include:

Managed Objects

Unreal Engine comes with a reflection system that can provide type information at runtime. This system enables the engine to interact with your classes at runtime, modify their properties and attributes through the editor, and extend them via Blueprints. The system also allows the engine to manage your objects automatically, using a mark-and-sweep garbage collector that cleans up unused objects during regular intervals.

To register a C++ class with the reflection system, you need to apply the UCLASS macro to the class. The Unreal Header Tool will expand this macro into the required code to make the system work. UHT stores this code in a .generated.h file that must be included in the original header file as the last #include.

The reflection system is not limited to classes. You can use USTRUCT, UENUM, and UINTERFACE to register structs, enum classes, and interfaces, respectively.

Delegates

Delegates are Unreal Engine's solution to event-driven programming. They provide a mechanism for invoking one or more bound functions when a specific event occurs. Delegates can be:

  • Single-cast: Can bind one function at a time.
  • Multi-cast: Can bind multiple functions at once.

Delegates may be statically bound at compile time or dynamically bound at runtime. Static delegates cannot be changed at runtime, while dynamic delegates can be bound and even unbound at runtime. Refer to Delegates for more info.


  1. When these alternatives were introduced, the C++ standard library was not as optimized as it is today. Modern implementations of the standard library are quite performant and memory-efficient, but it is still recommended to use the Unreal Engine alternatives for consistency and compatibility.