Coding conventions for Unreal Engine 4 for C++, Blueprint and Python

Project Setup
Assets
Blueprint
C++
Python

View the Project on GitHub JonasReich/OpenUnrealConventions

Home / C++

C++ Coding Conventions

NOTE: These pages are being rewritten as 'live' source code conventions
in the form of an Unreal Engine plugin.

See Open Unreal Coding Standard


Code Organization

Naming

Documentation

Formatting

STL / std Namespace

Do not use any of the functions and types defined in the std namespace!

For all essential functions there are unreal specific substitues including but not limited to:

std namespace UE4 replacement
static_cast<T>() StaticCast<T>() or Cast<T>() for UObjects
move<T>() MoveTemp<T>()
forward<T>() Forward<T>()
unique_ptr<T> UniquePtr<T>
shared_ptr<T> SharedPtr<T>
weak_ptr<T> WeakPtr<T>
vector<T> TArray<T>
array<T> TArray<T, TInlineAllocator<T>>
map<T, U> TMap<T, U>
tuple<T...> TTuple<T...>

The engine source code also contains a significant amount of type traits that substitute the std type traits.

Preprocessor / Defines / Macros

const correctness

Use const when possible for

Do not use const in the following situations:

Parameter Passing

Source: C++ Core Guidelines F.15:

Stick to the following table when possible and document decisions whenever you pick a different approach:

parameter functionality Cheap or impossible to copy type (e.g. int, FUnqiuePtr<T>) Cheap to move (e.g. TArray<T>, FString) or Moderate cost to move (e.g. TArray<TMap<T, U>>, BigPOD) or Don’t know (e.g. unfamiliar type, template) Expensive to move (e.g. BigPOD[])
Out X f() X f() f(X&)
In/Out f(X&) f(X&) f(X&)
In & read only f(X) f(const X&) f(const X&)
In & retain copy f(X) f(const X&) f(const X&)

When you really want to add explicit move semantics support, check if your parameter falls into one of the following cases:

parameter functionality Cheap or impossible to copy type (e.g. int, FUnqiuePtr<T>) Cheap to move (e.g. TArray<T>, FString) or Moderate cost to move (e.g. TArray<TMap<T, U>>, BigPOD) or Don’t know (e.g. unfamiliar type, template) Expensive to move (e.g. BigPOD[])
Out X f() X f() f(X&)
In/Out f(X&) f(X&) f(X&)
In & read only f(X) f(const X&) f(const X&)
In & retain copy f(X) f(const X&) + f(X&&) & move f(const X&)
In & move from f(X&&) f(X&&) f(X&&)

Constructor Overloads

Modern C++ Features (C++11 and higher)

Not all features of C++11, C++14 etc are supported by all UE4 target platforms. However following features are reccommended to use:

Include Style

To ensure your module’s header files can be included by other modules, you should stick to these two rules:

  1. Never use relative paths using ./ or ../ notation
  2. Is your module split in public/private folder?
    • Yes: Use paths relative to the module parent directory for module directory, e.g.
        #include "MyModule/SubFolder/HeaderFile.h"
      
    • No: Use paths relative to the module directory itself, e.g.
        #include "SubFolder/HeaderFile.h"
      

Fundamental Type Aliases

Instead of using built-in types like int and short, the UE4 typedefs should be used:

Standard types that may be used:

Literals

String and number literals may be used. Do not use raw string literals ("foo", L"bar"), but instead always use the TEXT("foo") macro to surround string literals, unless they are fed into other macros, such as INVTEXT("My culture invariant").

If you need FTexts for UI display, never convert from FString, always write localizable FTexts using LOCTEXT(), or culture invariants using INVTEXT() for dev UI that should not be translated:

// localizable button label
FText ButtonLabel = LOCTEXT("ButtonLabel", "Press Me!");

// culture invariant used for DEV UI, so it doesn't end up in loca kits
FText DevButtonLabel = LOCTEXT("DevButtonLabel", "Press Me! (only if you're a dev)");

Log Macros

Never use the LogTemp log category for anything other than temporary debug code. Always use/create an appropriate log cateogry using one of the declare/define log cateogry macros instead (see UE4 Community wiki).