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()andUPROPERTY()are markers for the Unreal Header Tool. The tool reads the headers before the compilation and writes*.generated.hfiles with reflection data.- Each marker must be on its own line.
- A header with a
UCLASSincludes itsName.generated.hfile as the last include. UPROPERTY()on a pointer tells the garbage collector that the object holds a reference. Unreal deletes aUObjectthat no reference reaches. A rawUObject*member withoutUPROPERTY()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#
- Architecture shows how the classes of ACRES connect.
- C++ Headers lists the public types and functions.
- Coding and Naming Conventions gives the rules for new code.