Unreal Engine C++ fundamentals
Unreal C++ is standard C++ augmented by a reflection layer generated by the Unreal Header Tool
(UHT). Getting the reflection macros right determines whether your code compiles, appears in
Blueprints, replicates correctly, and survives garbage collection.
When to use this skill
- Creating or editing any
U*/A* class or F* struct in C++.
- Exposing a member or function to Blueprints, the editor, or network replication.
- Diagnosing UHT errors ("Unrecognized type", "missing
generated.h", "GENERATED_BODY missing").
- Deciding between
TObjectPtr, raw pointer, TWeakObjectPtr, or TSharedPtr.
- Understanding how the CDO works or why a constructor runs in the editor.
Mental model
Three interlocking pieces:
- UObject is the base of the reflected, garbage-collected object graph. Every class that opts
into the system derives from it (directly or via
AActor, UActorComponent, etc.).
- UHT parses your headers before the compiler and emits a
<ClassName>.generated.h that
contains boilerplate for reflection, serialization, and Blueprint integration. You include this
file last and place GENERATED_BODY() inside the type.
- UClass (the runtime type descriptor) holds a Class Default Object (CDO) — one instance
constructed at startup with all defaults applied. New instances copy from the CDO. The
constructor runs on the CDO and in the editor; never put gameplay logic there.
UObjects are garbage-collected. Any UObject* you want kept alive must be stored in a UPROPERTY.
A plain C++ pointer is invisible to the GC and will dangle after the next collection.
Class prefixes (mandatory)
| Prefix |
Meaning |
Examples |
U |
UObject-derived (non-Actor) |
UActorComponent, UMyDataAsset |
A |
Actor-derived (world-placeable) |
AActor, AMyCharacter |
F |
Plain struct / non-UObject value type |
FVector, FMyConfig |
E |
Enum |
EMyState |
I |
Interface (the IFoo half of a UFoo/IFoo pair) |
IInteractable |
T |
Template |
TArray, TObjectPtr |
S |
Slate widget |
SButton |
The class name after the prefix must match the filename (minus prefix): AMyPawn lives in
MyPawn.h / MyPawn.cpp.
Anatomy of a UObject class
// MyActor.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h" // ALWAYS LAST include
UCLASS(Blueprintable, BlueprintType)
class MYGAME_API AMyActor : public AActor // MYGAME_API = module export macro
{
GENERATED_BODY()
public:
AMyActor();
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
float Health = 100.f;
UFUNCTION(BlueprintCallable, Category = "Stats")
void ApplyDamage(float Amount);
protected:
virtual void BeginPlay() override;
UPROPERTY(VisibleAnywhere)
TObjectPtr<USceneComponent> Root; // UPROPERTY keeps it alive in the GC graph
};
// MyActor.cpp
#include "MyActor.h"
AMyActor::AMyActor()
{
PrimaryActorTick.bCanEverTick = true;
Root = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
SetRootComponent(Root);
}
void AMyActor::BeginPlay()
{
Super::BeginPlay(); // call Super on all engine virtual overrides
}
void AMyActor::ApplyDamage(float Amount)
{
Health = FMath::Max(0.f, Health - Amount);
}
Four rules that prevent most build breaks:
#include "X.generated.h" is the last include in the header.
- Every reflected class/struct has
GENERATED_BODY().
- The class is annotated with the module API macro (
MYGAME_API) so other modules can link it.
- Always call
Super:: in overridden engine virtuals (BeginPlay, Tick, EndPlay, …).
UCLASS specifiers
Verified in ObjectMacros.h (namespace UC, line 792):
Blueprintable — the class can be subclassed in Blueprint.
BlueprintType — can be used as a Blueprint variable type.
Abstract — cannot be instantiated directly.
Config=Game — properties marked Config are read/written from *.ini files.
MinimalAPI — exports only the reflection boilerplate (Cast<>, etc.); use in leaf-module classes
to reduce link surface.
meta=(PrioritizeCategories="Stats") — editor ordering hints.
UPROPERTY specifiers
Verified in ObjectMacros.h (namespace UP, line 1046):
Edit / visibility (Details panel):
EditAnywhere — editable on CDO and placed instances.
EditDefaultsOnly — CDO (Blueprint defaults) only.
EditInstanceOnly — placed instances only.
VisibleAnywhere / VisibleDefaultsOnly / VisibleInstanceOnly — read-only in the editor.
Blueprint access:
BlueprintReadWrite — get and set in BP. BlueprintReadOnly — get only.
Common combos and meta:
Category = "Group" — organizes the Details panel (required for every exposed member).
meta=(ClampMin="0", ClampMax="100") — value ranges.
meta=(AllowPrivateAccess="true") — expose a private member to Blueprint.
Transient — not saved to disk. SaveGame — included in SaveGame serialization.
Replicated / ReplicatedUsing=OnRep_Func — network replication (see ue-networking-and-replication).
Instanced — for per-instance configurable subobjects.
Memory rule: any UObject* member you want kept alive must be a UPROPERTY. Use
TObjectPtr<UType> for class members (editor-aware, access-tracked in UE5); raw UType* is
acceptable for local variables and function parameters. Without UPROPERTY, the GC can collect the
object and leave a dangling pointer. See ue-memory-and-gc for the full pointer hierarchy.
UFUNCTION specifiers
Verified in ObjectMacros.h (namespace UF, line 945):
BlueprintCallable — callable from Blueprint event graphs.
BlueprintPure — no side effects; pure node (no exec pins).
BlueprintImplementableEvent — declared in C++, fully implemented in Blueprint; no C++ body.
BlueprintNativeEvent — C++ default (Func_Implementation) overridable in Blueprint.
CallInEditor — adds a button in the Details panel for editor-time execution.
Exec — registers as a console command.
Server / Client / NetMulticast + Reliable/Unreliable — RPCs.
BlueprintNativeEvent pattern:
UFUNCTION(BlueprintNativeEvent, Category="AI")
void OnSpotted(AActor* By);
void OnSpotted_Implementation(AActor* By); // C++ default, override in BP
USTRUCT, UENUM, UINTERFACE
// Value type struct — no GC, stack/value semantics
USTRUCT(BlueprintType)
struct FLoadout
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Loadout")
int32 Ammo = 0;
};
// Enum — uint8-backed required for Blueprint use
UENUM(BlueprintType)
enum class EDoorState : uint8 { Closed, Opening, Open, Closing };
// Interface: always declare both halves (U* is the UObject shell; I* is the C++ interface)
UINTERFACE(MinimalAPI, Blueprintable)
class UInteractable : public UInterface { GENERATED_BODY() };
class IInteractable
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintNativeEvent, Category="Interaction")
void Interact(AActor* Instigator);
};
Key differences between USTRUCT and UCLASS:
UScriptStruct (the runtime descriptor for USTRUCT) derives from UStruct, not UClass.
Struct instances are value types — no GC, no CDO, no NewObject.
UPROPERTY inside a struct still enables serialization and editor exposure; it does not imply
GC ownership (there is nothing for the GC to track in a value type).
- Prefer
USTRUCT for lightweight data bags (stats, configs, hit results). Use UCLASS when you
need GC lifetime, Blueprint subclassing, or per-instance identity.
See references/reflection-macros.md for the full specifier
reference with less-common options.
Object construction
| API |
When |
Notes |
CreateDefaultSubobject<T>(TEXT("Name")) |
Constructor only |
Creates owned subobject; names must be unique per class |
NewObject<T>(Outer) |
Runtime, non-Actor |
Use for any UObject that is not an Actor |
GetWorld()->SpawnActor<T>(Class, FTransform) |
Runtime, Actors |
See ue-actors-and-components |
Cast<T>(Obj) |
Anywhere |
Safe checked cast; returns null on failure — never static_cast |
IsValid(Obj) |
Anywhere |
True if non-null and not garbage; prefer over bare null check |
CreateDefaultSubobject is declared on UObject (Object.h:151). NewObject template
overloads are in UObjectGlobals.h (lines 1931, 1959, 1974).
The CDO is created by UClass::GetDefaultObject (Class.h:4519) the first time it is needed.
After construction the CDO is read-only; modify only through archetype/default propagation.
Full construction paths, CDO lifecycle, and PostInitProperties are in
references/uobject-lifecycle-and-cdo.md.
Pointer and ownership cheat sheet
| Need |
Use |
| UObject member you own / keep alive |
UPROPERTY() TObjectPtr<UType> |
| Local variable or function parameter |
raw UType* |
| Non-owning ref that may be destroyed |
TWeakObjectPtr<UType> — check .IsValid() before use |
| Non-UObject heap object, shared ownership |
TSharedPtr<T> / TSharedRef<T> |
| Asset reference loaded on demand |
TSoftObjectPtr<T> / TSoftClassPtr<T> |
TObjectPtr<T> (declared in ObjectPtr.h:519) is the modern form for UPROPERTY members in UE5.
Older code uses raw T* UPROPERTY() pointers, which still compile and work. Legacy code you
encounter will mix both styles.
Gotchas
- Forgot
UPROPERTY on a UObject member* → random crashes after GC. The most common bug.
generated.h not last / missing GENERATED_BODY() → cryptic UHT errors that appear
unrelated to the actual mistake.
- Gameplay logic in the constructor → runs on the CDO and in the editor; no world, no
gameplay. Always put gameplay init in
BeginPlay.
CreateDefaultSubobject outside the constructor → asserts (detected by
FObjectInitializer::AssertIfInConstructor, UObjectGlobals.h:1936).
NewObject with an empty name inside a constructor → also asserts; use
CreateDefaultSubobject instead.
- Calling editor-only API from runtime code → packaging failures; guard with
#if WITH_EDITOR.
UENUM not backed by uint8 → Blueprint-unusable; BlueprintType enum must be uint8.
ClassDefaultObject accessed directly → deprecated as of UE 5.6; use
GetDefaultObject()/GetDefault<T>() instead (Class.h:4045).
FName/FString/FText mix-ups → see ue-core-types-and-containers.
Version notes
TObjectPtr<T> (UPROPERTY member idiom) and TObjectPtr-backed GC barrier were introduced in
UE5. Pre-5.0 code uses raw T* UPROPERTY(), which still works but lacks editor access tracking.
MarkPendingKill() was replaced by MarkAsGarbage() in UE5; with gc.PendingKillEnabled=false
(the new default), the GC no longer auto-nulls pointers — use IsValid() and clear references
in EndPlay/callbacks.
ClassDefaultObject was deprecated as a direct field access in 5.6; use GetDefaultObject().
References & source material
Engine source (UE 5.8, under Engine/Source/Runtime/CoreUObject/Public/UObject/):
Object.h:98 — UObject class definition; :151 — CreateDefaultSubobject; :226 —
PostInitProperties; :361 — BeginDestroy; :368 — IsReadyForFinishDestroy; :382 —
FinishDestroy; :1886 — IsValid().
ObjectMacros.h:778 — UPROPERTY/UFUNCTION/USTRUCT/UENUM macro stubs; :800 —
GENERATED_BODY; :832 — UCLASS specifiers; :985 — UFUNCTION specifiers; :1086 —
UPROPERTY specifiers; :1216 — USTRUCT specifiers.
Class.h:495 — UStruct; :1774 — UScriptStruct; :3893 — UClass; :4045 —
deprecated ClassDefaultObject field (5.6+); :4519 — GetDefaultObject().
UObjectGlobals.h:1931 — NewObject<T>(Outer, Class, Name, …); :1959 —
NewObject<T>(Outer) (no name); :1974 — NewObject<T>(Outer, Name, …).
ObjectPtr.h:519 — TObjectPtr<T>.
Interface.h:18 — UInterface base class.
Official docs (UE 5.8):
Deep-dive references in this skill:
- references/reflection-macros.md — full specifier tables for
UCLASS/UPROPERTY/UFUNCTION/USTRUCT/UENUM/UINTERFACE with less-common options.
- references/uobject-lifecycle-and-cdo.md — CDO
construction,
PostInitProperties, GC callbacks, BeginDestroy/FinishDestroy.
- references/object-creation-and-gc.md —
NewObject vs
CreateDefaultSubobject, object flags, GC roots, clustering, and ownership patterns.
Cross-reference sibling skills:
ue-memory-and-gc — deep dive on pointer types, weak pointers, GC tuning.
ue-actors-and-components — Actor/component lifecycle, spawning, ticking.
ue-blueprint-cpp-integration — exposing C++ types to Blueprint in depth.
ue-module-and-build-system — the module API macro, Build.cs, UHT pipeline details.
1---2name: ue-cpp-fundamentals3description: Write correct Unreal Engine C++ using the UObject reflection system — UCLASS/USTRUCT/ UENUM/UINTERFACE macros, UPROPERTY and UFUNCTION specifiers, GENERATED_BODY, the *.generated.h pipeline, class prefixes (U/A/F/E/I), module API export macros, the Class Default Object (CDO), NewObject vs CreateDefaultSubobject, garbage-collection-safe ownership, and UClass vs UScriptStruct internals. Use when authoring or editing any UE C++ class, exposing members or functions to Blueprints or replication, fixing UHT/reflection build errors, or choosing between pointer and ownership types.4---56# Unreal Engine C++ fundamentals78Unreal C++ is standard C++ augmented by a **reflection layer** generated by the Unreal Header Tool9(UHT). Getting the reflection macros right determines whether your code compiles, appears in10Blueprints, replicates correctly, and survives garbage collection.1112## When to use this skill1314- Creating or editing any `U*`/`A*` class or `F*` struct in C++.15- Exposing a member or function to Blueprints, the editor, or network replication.16- Diagnosing UHT errors ("Unrecognized type", "missing `generated.h`", "GENERATED_BODY missing").17- Deciding between `TObjectPtr`, raw pointer, `TWeakObjectPtr`, or `TSharedPtr`.18- Understanding how the CDO works or why a constructor runs in the editor.1920## Mental model2122Three interlocking pieces:23241. **UObject** is the base of the reflected, garbage-collected object graph. Every class that opts25 into the system derives from it (directly or via `AActor`, `UActorComponent`, etc.).262. **UHT** parses your headers before the compiler and emits a `<ClassName>.generated.h` that27 contains boilerplate for reflection, serialization, and Blueprint integration. You include this28 file **last** and place `GENERATED_BODY()` inside the type.293. **UClass** (the runtime type descriptor) holds a **Class Default Object (CDO)** — one instance30 constructed at startup with all defaults applied. New instances copy from the CDO. The31 constructor runs on the CDO and in the editor; never put gameplay logic there.3233UObjects are garbage-collected. Any UObject* you want kept alive must be stored in a `UPROPERTY`.34A plain C++ pointer is invisible to the GC and will dangle after the next collection.3536## Class prefixes (mandatory)3738| Prefix | Meaning | Examples |39|---|---|---|40| `U` | UObject-derived (non-Actor) | `UActorComponent`, `UMyDataAsset` |41| `A` | Actor-derived (world-placeable) | `AActor`, `AMyCharacter` |42| `F` | Plain struct / non-UObject value type | `FVector`, `FMyConfig` |43| `E` | Enum | `EMyState` |44| `I` | Interface (the `IFoo` half of a `UFoo`/`IFoo` pair) | `IInteractable` |45| `T` | Template | `TArray`, `TObjectPtr` |46| `S` | Slate widget | `SButton` |4748The class name after the prefix must match the filename (minus prefix): `AMyPawn` lives in49`MyPawn.h / MyPawn.cpp`.5051## Anatomy of a UObject class5253```cpp54// MyActor.h55#pragma once5657#include "CoreMinimal.h"58#include "GameFramework/Actor.h"59#include "MyActor.generated.h" // ALWAYS LAST include6061UCLASS(Blueprintable, BlueprintType)62class MYGAME_API AMyActor : public AActor // MYGAME_API = module export macro63{64 GENERATED_BODY()6566public:67 AMyActor();6869 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")70 float Health = 100.f;7172 UFUNCTION(BlueprintCallable, Category = "Stats")73 void ApplyDamage(float Amount);7475protected:76 virtual void BeginPlay() override;7778 UPROPERTY(VisibleAnywhere)79 TObjectPtr<USceneComponent> Root; // UPROPERTY keeps it alive in the GC graph80};81```8283```cpp84// MyActor.cpp85#include "MyActor.h"8687AMyActor::AMyActor()88{89 PrimaryActorTick.bCanEverTick = true;90 Root = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));91 SetRootComponent(Root);92}9394void AMyActor::BeginPlay()95{96 Super::BeginPlay(); // call Super on all engine virtual overrides97}9899void AMyActor::ApplyDamage(float Amount)100{101 Health = FMath::Max(0.f, Health - Amount);102}103```104105Four rules that prevent most build breaks:106- `#include "X.generated.h"` is the **last** include in the header.107- Every reflected class/struct has `GENERATED_BODY()`.108- The class is annotated with the module API macro (`MYGAME_API`) so other modules can link it.109- Always call `Super::` in overridden engine virtuals (`BeginPlay`, `Tick`, `EndPlay`, …).110111## UCLASS specifiers112113Verified in `ObjectMacros.h` (namespace `UC`, line 792):114115- `Blueprintable` — the class can be subclassed in Blueprint.116- `BlueprintType` — can be used as a Blueprint variable type.117- `Abstract` — cannot be instantiated directly.118- `Config=Game` — properties marked `Config` are read/written from `*.ini` files.119- `MinimalAPI` — exports only the reflection boilerplate (Cast<>, etc.); use in leaf-module classes120 to reduce link surface.121- `meta=(PrioritizeCategories="Stats")` — editor ordering hints.122123## UPROPERTY specifiers124125Verified in `ObjectMacros.h` (namespace `UP`, line 1046):126127**Edit / visibility (Details panel):**128- `EditAnywhere` — editable on CDO and placed instances.129- `EditDefaultsOnly` — CDO (Blueprint defaults) only.130- `EditInstanceOnly` — placed instances only.131- `VisibleAnywhere` / `VisibleDefaultsOnly` / `VisibleInstanceOnly` — read-only in the editor.132133**Blueprint access:**134- `BlueprintReadWrite` — get and set in BP. `BlueprintReadOnly` — get only.135136**Common combos and meta:**137- `Category = "Group"` — organizes the Details panel (required for every exposed member).138- `meta=(ClampMin="0", ClampMax="100")` — value ranges.139- `meta=(AllowPrivateAccess="true")` — expose a `private` member to Blueprint.140- `Transient` — not saved to disk. `SaveGame` — included in SaveGame serialization.141- `Replicated` / `ReplicatedUsing=OnRep_Func` — network replication (see `ue-networking-and-replication`).142- `Instanced` — for per-instance configurable subobjects.143144**Memory rule:** any `UObject*` member you want kept alive must be a `UPROPERTY`. Use145`TObjectPtr<UType>` for class members (editor-aware, access-tracked in UE5); raw `UType*` is146acceptable for local variables and function parameters. Without `UPROPERTY`, the GC can collect the147object and leave a dangling pointer. See `ue-memory-and-gc` for the full pointer hierarchy.148149## UFUNCTION specifiers150151Verified in `ObjectMacros.h` (namespace `UF`, line 945):152153- `BlueprintCallable` — callable from Blueprint event graphs.154- `BlueprintPure` — no side effects; pure node (no exec pins).155- `BlueprintImplementableEvent` — declared in C++, fully implemented in Blueprint; no C++ body.156- `BlueprintNativeEvent` — C++ default (`Func_Implementation`) overridable in Blueprint.157- `CallInEditor` — adds a button in the Details panel for editor-time execution.158- `Exec` — registers as a console command.159- `Server` / `Client` / `NetMulticast` + `Reliable`/`Unreliable` — RPCs.160161`BlueprintNativeEvent` pattern:162163```cpp164UFUNCTION(BlueprintNativeEvent, Category="AI")165void OnSpotted(AActor* By);166void OnSpotted_Implementation(AActor* By); // C++ default, override in BP167```168169## USTRUCT, UENUM, UINTERFACE170171```cpp172// Value type struct — no GC, stack/value semantics173USTRUCT(BlueprintType)174struct FLoadout175{176 GENERATED_BODY()177 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Loadout")178 int32 Ammo = 0;179};180181// Enum — uint8-backed required for Blueprint use182UENUM(BlueprintType)183enum class EDoorState : uint8 { Closed, Opening, Open, Closing };184185// Interface: always declare both halves (U* is the UObject shell; I* is the C++ interface)186UINTERFACE(MinimalAPI, Blueprintable)187class UInteractable : public UInterface { GENERATED_BODY() };188189class IInteractable190{191 GENERATED_BODY()192public:193 UFUNCTION(BlueprintNativeEvent, Category="Interaction")194 void Interact(AActor* Instigator);195};196```197198Key differences between `USTRUCT` and `UCLASS`:199- `UScriptStruct` (the runtime descriptor for USTRUCT) derives from `UStruct`, not `UClass`.200 Struct instances are **value types** — no GC, no CDO, no `NewObject`.201- `UPROPERTY` inside a struct still enables serialization and editor exposure; it does not imply202 GC ownership (there is nothing for the GC to track in a value type).203- Prefer `USTRUCT` for lightweight data bags (stats, configs, hit results). Use `UCLASS` when you204 need GC lifetime, Blueprint subclassing, or per-instance identity.205206See [references/reflection-macros.md](references/reflection-macros.md) for the full specifier207reference with less-common options.208209## Object construction210211| API | When | Notes |212|---|---|---|213| `CreateDefaultSubobject<T>(TEXT("Name"))` | Constructor only | Creates owned subobject; names must be unique per class |214| `NewObject<T>(Outer)` | Runtime, non-Actor | Use for any UObject that is not an Actor |215| `GetWorld()->SpawnActor<T>(Class, FTransform)` | Runtime, Actors | See `ue-actors-and-components` |216| `Cast<T>(Obj)` | Anywhere | Safe checked cast; returns null on failure — never `static_cast` |217| `IsValid(Obj)` | Anywhere | True if non-null and not garbage; prefer over bare null check |218219`CreateDefaultSubobject` is declared on `UObject` (`Object.h`:151). `NewObject` template220overloads are in `UObjectGlobals.h` (lines 1931, 1959, 1974).221222The **CDO** is created by `UClass::GetDefaultObject` (`Class.h`:4519) the first time it is needed.223After construction the CDO is read-only; modify only through archetype/default propagation.224225Full construction paths, CDO lifecycle, and `PostInitProperties` are in226[references/uobject-lifecycle-and-cdo.md](references/uobject-lifecycle-and-cdo.md).227228## Pointer and ownership cheat sheet229230| Need | Use |231|---|---|232| UObject member you own / keep alive | `UPROPERTY() TObjectPtr<UType>` |233| Local variable or function parameter | raw `UType*` |234| Non-owning ref that may be destroyed | `TWeakObjectPtr<UType>` — check `.IsValid()` before use |235| Non-UObject heap object, shared ownership | `TSharedPtr<T>` / `TSharedRef<T>` |236| Asset reference loaded on demand | `TSoftObjectPtr<T>` / `TSoftClassPtr<T>` |237238`TObjectPtr<T>` (declared in `ObjectPtr.h`:519) is the modern form for UPROPERTY members in UE5.239Older code uses raw `T* UPROPERTY()` pointers, which still compile and work. Legacy code you240encounter will mix both styles.241242## Gotchas243244- **Forgot `UPROPERTY` on a UObject* member** → random crashes after GC. The most common bug.245- **`generated.h` not last / missing `GENERATED_BODY()`** → cryptic UHT errors that appear246 unrelated to the actual mistake.247- **Gameplay logic in the constructor** → runs on the CDO and in the editor; no world, no248 gameplay. Always put gameplay init in `BeginPlay`.249- **`CreateDefaultSubobject` outside the constructor** → asserts (detected by250 `FObjectInitializer::AssertIfInConstructor`, `UObjectGlobals.h`:1936).251- **`NewObject` with an empty name inside a constructor** → also asserts; use252 `CreateDefaultSubobject` instead.253- **Calling editor-only API from runtime code** → packaging failures; guard with `#if WITH_EDITOR`.254- **`UENUM` not backed by `uint8`** → Blueprint-unusable; `BlueprintType` enum must be `uint8`.255- **`ClassDefaultObject` accessed directly** → deprecated as of UE 5.6; use256 `GetDefaultObject()`/`GetDefault<T>()` instead (`Class.h`:4045).257- **`FName`/`FString`/`FText` mix-ups** → see `ue-core-types-and-containers`.258259## Version notes260261- `TObjectPtr<T>` (UPROPERTY member idiom) and `TObjectPtr`-backed GC barrier were introduced in262 UE5. Pre-5.0 code uses raw `T* UPROPERTY()`, which still works but lacks editor access tracking.263- `MarkPendingKill()` was replaced by `MarkAsGarbage()` in UE5; with `gc.PendingKillEnabled=false`264 (the new default), the GC no longer auto-nulls pointers — use `IsValid()` and clear references265 in `EndPlay`/callbacks.266- `ClassDefaultObject` was deprecated as a direct field access in 5.6; use `GetDefaultObject()`.267268## References & source material269270Engine source (UE 5.8, under `Engine/Source/Runtime/CoreUObject/Public/UObject/`):271- `Object.h`:98 — `UObject` class definition; `:151` — `CreateDefaultSubobject`; `:226` —272 `PostInitProperties`; `:361` — `BeginDestroy`; `:368` — `IsReadyForFinishDestroy`; `:382` —273 `FinishDestroy`; `:1886` — `IsValid()`.274- `ObjectMacros.h`:778 — `UPROPERTY`/`UFUNCTION`/`USTRUCT`/`UENUM` macro stubs; `:800` —275 `GENERATED_BODY`; `:832` — `UCLASS` specifiers; `:985` — `UFUNCTION` specifiers; `:1086` —276 `UPROPERTY` specifiers; `:1216` — `USTRUCT` specifiers.277- `Class.h`:495 — `UStruct`; `:1774` — `UScriptStruct`; `:3893` — `UClass`; `:4045` —278 deprecated `ClassDefaultObject` field (5.6+); `:4519` — `GetDefaultObject()`.279- `UObjectGlobals.h`:1931 — `NewObject<T>(Outer, Class, Name, …)`; `:1959` —280 `NewObject<T>(Outer)` (no name); `:1974` — `NewObject<T>(Outer, Name, …)`.281- `ObjectPtr.h`:519 — `TObjectPtr<T>`.282- `Interface.h`:18 — `UInterface` base class.283284Official docs (UE 5.8):285- Objects — <https://dev.epicgames.com/documentation/unreal-engine/objects-in-unreal-engine>286- UObject Instance Creation —287 <https://dev.epicgames.com/documentation/unreal-engine/creating-objects-in-unreal-engine>288- Unreal Object Handling —289 <https://dev.epicgames.com/documentation/unreal-engine/unreal-object-handling-in-unreal-engine>290- Properties —291 <https://dev.epicgames.com/documentation/unreal-engine/unreal-engine-uproperties>292- UFunctions — <https://dev.epicgames.com/documentation/unreal-engine/ufunctions-in-unreal-engine>293- Unreal Interfaces —294 <https://dev.epicgames.com/documentation/unreal-engine/interfaces-in-unreal-engine>295- Metadata Specifiers —296 <https://dev.epicgames.com/documentation/unreal-engine/metadata-specifiers-in-unreal-engine>297298Deep-dive references in this skill:299- [references/reflection-macros.md](references/reflection-macros.md) — full specifier tables for300 UCLASS/UPROPERTY/UFUNCTION/USTRUCT/UENUM/UINTERFACE with less-common options.301- [references/uobject-lifecycle-and-cdo.md](references/uobject-lifecycle-and-cdo.md) — CDO302 construction, `PostInitProperties`, GC callbacks, `BeginDestroy`/`FinishDestroy`.303- [references/object-creation-and-gc.md](references/object-creation-and-gc.md) — `NewObject` vs304 `CreateDefaultSubobject`, object flags, GC roots, clustering, and ownership patterns.305306Cross-reference sibling skills:307- `ue-memory-and-gc` — deep dive on pointer types, weak pointers, GC tuning.308- `ue-actors-and-components` — Actor/component lifecycle, spawning, ticking.309- `ue-blueprint-cpp-integration` — exposing C++ types to Blueprint in depth.310- `ue-module-and-build-system` — the module API macro, `Build.cs`, UHT pipeline details.