Skip to content

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.h include must be the last include in the header. Otherwise the build breaks with cryptic errors.
  • REPHRASED_DEMO_API is the module's export macro. Required on every UCLASS/USTRUCT declared in this module.
  • Class prefix is meaningful: A for actors, U for non-actor UObjects, F for plain structs, I for interfaces, E for enums, T for 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 in UFUNCTIONs.
  • Replicated / ReplicatedUsing — networking. We are single-player, so never used.
  • SaveGame — the only UPROPERTY specifier that matters for save/load (see the SaveLoad page).

Source files

  • Source/Rephrased_Demo/RuneSystem/Components/RuneEffectComponent.h — typical BlueprintNativeEvent pattern in practice.
  • Source/Rephrased_Demo/RuneDataAsset.h — heavy use of meta = (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.