Skip to content

Unreal for C++ Developers#

This page explains the Unreal Engine concepts that the ACRES source code uses. Read it when you know C++ but not Unreal.

The Project on Disk#

The Unreal project is in the folder Acres.

Path Content
Acres/Acres.uproject The project file. The editor opens this file.
Acres/Config/*.ini Engine and game settings: the renderer, the physics rate, the default map, the input bindings.
Acres/Source/Acres/ The C++ code of the game. It is one module.
Acres/Source/*.Target.cs The build targets for the game and the editor. The language is C#.
Acres/Content/ The assets (.uasset, .umap). Git LFS stores them.
Acres/Content/Simulation/ JSON files and binary grids. The simulation reads them at run time.
Acres/Shaders/ The GPU shaders of the project (HLSL in .usf and .ush files).

A .uasset file is a binary asset: a mesh, a texture, a material or a particle system. A .umap file is a level. Unreal also names a level a map. The game uses one map, Maps/V03ACRE. It contains the farm.

The file Acres.Build.cs lists the engine modules that the code links. The build tool of Unreal (UnrealBuildTool) reads this file.

Objects, Actors and Components#

Unreal has an object system above C++. A class of this system derives from UObject and contains macros.

UCLASS()
class AAcresNpcWorker : public AActor
{
    GENERATED_BODY()
public:
    UPROPERTY()
    TObjectPtr<USkeletalMeshComponent> Body;
};
  • UCLASS(), GENERATED_BODY() and UPROPERTY() are markers for the Unreal Header Tool. The tool reads the headers before the compilation and writes *.generated.h files with reflection data.
  • Each marker must be on its own line.
  • A header with a UCLASS includes its Name.generated.h file as the last include.
  • UPROPERTY() on a pointer tells the garbage collector that the object holds a reference. Unreal deletes a UObject that no reference reaches. A raw UObject* member without UPROPERTY() can thus point to a deleted object.

The name prefixes are a convention that the tools enforce.

Prefix Use
U A class that derives from UObject.
A An actor.
F A plain struct or class.
E An enumeration.
T A template.
S A Slate widget.
I An interface.

An actor (AActor) is an object in the world: a vehicle, a worker, the sun or a barn. An actor contains components (UActorComponent). A USceneComponent has a transform. Scene components form a tree of attached parts.

A pawn (APawn) is an actor that a player or a program controls. The game has three pawn classes.

Class Function
AAcresVehiclePawn The Maxxum or the Polaris. One instance for each agent.
AAcresMenuPawn The camera of the menu.
AAcresShellPawn A free camera for the inspection of the map.

The game mode selects the pawn when a map loads. The game mode of ACRES is AAcresShellGameMode. It reads the command line.

Option Pawn
-VehicleDemo The vehicle pawn. The simulation starts immediately.
-ShellView The free camera.
No option The menu pawn.

Life Cycle#

The engine calls these functions of an actor.

Function Time Thread
Constructor When the engine makes the class default object and each instance. Game
BeginPlay() One time, when the actor enters a world that runs. Game
Tick(float DeltaSeconds) Each rendered frame. Game
AsyncPhysicsTickActor(float Dt, float SimTime) Each physics step. The rate is 120 Hz in ACRES. Physics
EndPlay(Reason) When the actor leaves the world. Game

Threads#

The code uses four types of thread.

Thread Work
Game thread It owns the world. BeginPlay, Tick, the HUD and the UI run here. Code that changes an actor must run here.
Physics thread Chaos, the physics engine of Unreal, runs here at a fixed step. The vehicle pawn computes its forces here.
Render thread It draws the frame. ENQUEUE_RENDER_COMMAND puts a lambda into its queue. The camera readback and the GPU LiDAR use it.
Worker threads The soil-water model and the sensor writer each have a thread (FRunnable). Camera processing uses the thread pool.

Data moves between threads in small structs under a lock. FCriticalSection is equivalent to std::mutex. FScopeLock is equivalent to std::lock_guard.

Types#

Unreal Equivalent
TArray<T> std::vector<T>. Num() gives the size. Add appends an element.
TMap<K,V>, TSet<T> std::unordered_map, std::unordered_set.
FString A wide string. *Str gives a const TCHAR*.
FName An interned name. The comparison ignores the case and is fast.
FText Display text for the UI. It supports translation.
TEXT("...") The macro for a wide string literal.
TSharedPtr, TSharedRef, TUniquePtr, TWeakPtr std::shared_ptr, a shared_ptr that is never null, std::unique_ptr, std::weak_ptr.
TObjectPtr<T> A pointer to a UObject. Use it with UPROPERTY().
TWeakObjectPtr<T> A pointer to a UObject that becomes null when the engine deletes the object.
FVector, FVector2D Vectors of doubles with three and two elements.
FRotator Pitch, yaw and roll in degrees.
FQuat, FTransform A quaternion. A rotation with a translation and a scale.
check(x) An assertion that stays in Development builds.
UE_LOG(LogTemp, Display, TEXT("..."), ...) A log line with printf format.
FParse::Param(FCommandLine::Get(), TEXT("Name")) Reads a command-line switch.
FParse::Value(FCommandLine::Get(), TEXT("Name="), Out) Reads a command-line value.

Units and Axes#

Unreal measures lengths in centimetres. The models of ACRES use SI units: metres, newtons, seconds and radians. The code divides or multiplies by 100 where a position moves between the two systems. A force for Chaos has the unit kg·cm/s².

The world of Unreal is left-handed with Z up. In this project X points east and Y points south. A yaw of 0° points east. A yaw of 90° points south.

The outputs of the simulator use the conventions of robotics. World positions are ENU (east, north, up). The vehicle body frame is FLU (forward, left, up). The ACRE Scene gives the frames and their conversions.

Slate#

The menu uses Slate, the C++ UI library of Unreal. Slate code is declarative.

SNew(SVerticalBox)
+ SVerticalBox::Slot().AutoHeight()
[
    SNew(STextBlock).Text(FText::FromString(TEXT("ACRES")))
]
+ SVerticalBox::Slot().AutoHeight()
[
    SNew(SButton).OnClicked_Lambda([] { return FReply::Handled(); })
];
Element Function
SNew(Type) Makes a widget.
.Property(value) Sets a property.
+ Slot() Adds a child slot to a container.
[ ... ] Puts a widget into the slot.
Text_Lambda Takes a lambda. Slate calls it each frame, so the label stays current.

Rendering Objects#

The weather code and the sensor code use these rendering objects.

Object Function
Dynamic material instance A copy of a material. Code can change its parameters at run time.
Material parameter collection A set of global shader parameters. MPC_AcresWeather holds the wind and the wetness.
Scene capture component and render target They render the world from a second viewpoint into a texture. The sensor camera uses them.
Niagara The particle system. The rain uses it.
Nanite, Lumen, virtual shadow maps The renderer features for dense geometry, global illumination and shadows.

Acres/Config/DefaultEngine.ini sets the renderer features. Platforms and GPU Tiers describes the settings that change with the GPU.

Next Steps#