Unreal C++ extensions¶
Unreal extends C++ with a reflection system so the editor, Blueprints, GC, networking, and serialization can introspect your types. The extra macros look heavy at first but they are how everything talks to everything else. If you skip them, the engine cannot see your code.
The macros that matter¶
| Macro | What it tags | Why |
|---|---|---|
UCLASS() |
A class derived from UObject |
Engine sees the class. Required for GC tracking, Blueprint subclassing, asset references. |
USTRUCT() |
A POD-like struct | Engine sees the struct, can serialize it, expose to Blueprints, store in UPROPERTY containers. |
UENUM() |
An enum | Editor dropdowns, Blueprint switches, network serialization. |
UPROPERTY() |
A member variable | GC tracks it, editor shows it, Blueprint can read/write it, save game can serialize it. |
UFUNCTION() |
A method | Blueprint can call it, RPC can route to it, delegates can bind to it. |
UINTERFACE() / IFoo |
An interface | Polymorphic interface that works in both C++ and Blueprint. |
GENERATED_BODY() |
First line inside a UCLASS/USTRUCT/UINTERFACE body |
Splices in the reflection-generated boilerplate. Required. |
The header pattern¶
Every reflected type follows a fixed shape:
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h" // must be the LAST include
UCLASS()
class REPHRASED_DEMO_API AMyActor : public AActor
{
GENERATED_BODY()
public:
AMyActor();
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "My Actor")
float SomeFloat = 1.0f;
UFUNCTION(BlueprintCallable, Category = "My Actor")
void DoThing();
};
Things that bite people coming from regular C++:
- The
*.generated.hinclude must be the last include in the header. Otherwise the build breaks with cryptic errors. REPHRASED_DEMO_APIis the module's export macro. Required on everyUCLASS/USTRUCTdeclared in this module.- Class prefix is meaningful:
Afor actors,Ufor non-actorUObjects,Ffor plain structs,Ifor interfaces,Efor enums,Tfor templates. The reflection system expects this and the editor enforces it on rename.
UPROPERTY specifiers in this codebase¶
These are the ones you will see most often. Full list in the Unreal docs.
| Specifier | Effect |
|---|---|
EditAnywhere |
Editable on the CDO (defaults) and per-instance in the level. |
EditDefaultsOnly |
Editable only on the CDO (Class Default Object). Per-instance editing disabled. |
EditInstanceOnly |
Editable only on placed instances. Defaults are locked. |
VisibleAnywhere |
Read-only in the editor. |
BlueprintReadWrite |
Blueprint can read and write. |
BlueprintReadOnly |
Blueprint can only read. |
Category = "Foo" |
Editor section heading. Use a real one; do not leave it default. |
meta = (EditCondition = "bSomething") |
Field is greyed out unless bSomething is true. |
meta = (EditCondition = "...", EditConditionHides) |
Field disappears entirely instead of greying out. |
meta = (ClampMin = "0", ClampMax = "10") |
Numeric clamp in the editor. Does not enforce at runtime. |
UFUNCTION specifiers in this codebase¶
| Specifier | Effect |
|---|---|
BlueprintCallable |
Blueprint can call this from a graph. |
BlueprintPure |
Same, but treats the call as a pure node (no exec pin). For getters that don't mutate state. |
BlueprintNativeEvent |
C++ provides a default _Implementation. Blueprint can override the function. |
BlueprintImplementableEvent |
C++ declares the signature only. Blueprint must implement. |
BlueprintAssignable |
For UPROPERTY delegates: Blueprint can bind. |
For BlueprintNativeEvent, the signature in the header looks like:
UFUNCTION(BlueprintNativeEvent, Category = "Effect")
void OnEffectApplied(URuneDataAsset* Verb);
virtual void OnEffectApplied_Implementation(URuneDataAsset* Verb);
Calling code calls OnEffectApplied(...) (the wrapper). Blueprint subclasses can override; if they do, the C++ _Implementation is replaced. If they don't, _Implementation runs.
Delegates¶
Multicast delegates are how systems broadcast events without coupling. The pattern:
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSomethingHappened, AActor*, Actor);
UPROPERTY(BlueprintAssignable, Category = "Events")
FOnSomethingHappened OnSomethingHappened;
DYNAMIC means the delegate is reflected (Blueprint can bind). The _OneParam (or _TwoParams, etc.) variant is required when the event carries arguments. Names are F-prefixed.
Things you rarely need¶
UPARAM(ref)for in/out reference parameters inUFUNCTIONs.Replicated/ReplicatedUsing— networking. We are single-player, so never used.SaveGame— the onlyUPROPERTYspecifier that matters for save/load (see the SaveLoad page).
Source files¶
Source/Rephrased_Demo/RuneSystem/Components/RuneEffectComponent.h— typicalBlueprintNativeEventpattern in practice.Source/Rephrased_Demo/RuneDataAsset.h— heavy use ofmeta = (EditCondition, EditConditionHides)for noun-vs-verb fields.
Change history¶
- 2026-05-23 — Gabriel Li — Moved under Unreal basics track (skippable for experienced UE engineers).
- 2026-05-08 — Gabriel Li — Added baseline change history section for weekly wiki maintenance.