This is not another topic in the course, but a compass over all the others. Twelve "Whys" that the engine solves with the same way of thinking over and over again — once you understand the train of thought itself, each subsequent engine system stops being a new set of facts to memorize and becomes a predictable consequence of the same reasoning.
Project rule: less magic after each topic
The course's goal is not to "show the API." The goal is that after each chapter, what previously looked like engine magic becomes a logical consequence of the architecture. After the Reflection chapter, it's clear why UCLASS, UPROPERTY, and UFUNCTION are needed. After the lifecycle chapter, it's clear why certain things cannot be done in the constructor. After the Gameplay Framework, it's obvious why logic is split between GameMode, PlayerController, PlayerState, and Character. This page is not a replacement for those topics, but their common denominator: the eleven different "whys" below are actually variations of the same question asked of different parts of the engine.
The main goal of learning
After completing the course, the reader should learn to independently make engineering decisions in Unreal Engine — not memorize facts about specific classes, but be able to: independently design the architecture of a new game system; read Unreal Engine source code without fear of an unfamiliar file; understand the reasons for the existence of any engine system, even one not covered in the course; find a solution in an unfamiliar part of the engine by analogy with an already understood way of thinking, rather than by trial and error; understand the trade-offs behind a specific architectural decision by Epic — and be able to articulate them in words, not just quote the conclusion.
The main goal of the course is to make the Unreal Engine documentation eventually unnecessary for the reader. Not because they memorized everything, but because they learned to reproduce the reasoning with which the documentation itself was written.
Why is almost everything in gameplay code a UObject?
Because "being a UObject" is not inheritance for the sake of inheritance, but a one-time purchase of three things at once: visibility for the Garbage Collector, visibility for Reflection (and thus for Blueprint/the editor), and a unified serialization mechanism. Writing any of these three systems from scratch for a "lightweight" type without UObject means solving an already solved problem a second time.
Deep dive → UObject: object architecture
Why is almost everything a pointer, not a value?
A UObject is a unit of identity and ownership (via Outer), which the Garbage Collector tracks by the address of the specific object in memory, not by its value. Copying a UObject "by value" would mean either breaking this identity (two different objects with the same data are not the same thing for the GC and Reflection), or secretly still copying by reference — so the engine makes this reference nature explicit via a pointer, rather than hiding it.
Deep dive → Smart pointers and GC
Why is there a Garbage Collector?
The graph of game objects in real-time is not a tree with a single owner, but a network of cross-references (an actor references a component, a component references another actor, which references back), where manually tracking "who was the last to stop referencing" is practically impossible without leaks or premature freeing. The GC solves this by tracking reachability from the root, rather than reference counting manually.
Deep dive → Garbage Collector
Why is there Reflection?
The editor, Blueprint, and the serialization system need to know about your C++ class's fields and functions at runtime — something that C++ fundamentally does not provide (the language has no runtime information about arbitrary class fields). The Unreal Header Tool solves this by generating this description in advance, from macros like UPROPERTY, rather than forcing the engine to guess from the binary.
Deep dive → Reflection
Why is there a Component?
Because the capabilities of gameplay entities ("has health", "has inventory") are a "has-a" relationship, not an "is-a" one, and inheritance, which correctly models "is-a", when used to express "has-a", leads to a combinatorial explosion of classes for every new independent capability.
Deep dive → UActorComponent
Why Composition over inheritance?
Because composition is the only one among the three attempted approaches (inheritance, interfaces, templates) that simultaneously provides independent enable/disable of a capability, physical storage of state, and full Reflection/Blueprint visibility — interfaces provide only a contract without state, templates are invisible to UHT.
Deep dive → UActorComponent
Why are there Modules?
A codebase of the engine's size cannot be compiled in a reasonable time and does not have manageable dependency boundaries as a single monolithic binary. A module is a separate compilation unit with its own build file and an explicit list of dependencies on other modules, which allows rebuilding only what has actually changed and physically prevents one part of the engine from pulling in what it doesn't need (e.g., editor code into a packaged game).
Article soon
Why are there Plugins?
A module is a compilation unit, but not a distribution unit. A plugin packages one or more modules along with content and config into a standalone, enable/disable feature for a specific project — so an engine extension doesn't require forking or patching the engine source, which would otherwise diverge with every subsequent engine update.
Article soon
Why is there a Subsystem?
A homemade singleton/global variable doesn't mesh well with the fact that multiple "worlds" can exist simultaneously in Unreal (editor + Play-In-Editor concurrently, multiple clients in one process during testing) — global state has nowhere to unambiguously "belong" to. A Subsystem is a UObject with an automatic lifetime managed by the engine and tied to a specific, explicit boundary (Engine/GameInstance/World/LocalPlayer), so it doesn't outlive its boundary and doesn't get mixed up between parallel worlds.
Article soon
Why are there Gameplay Tags?
A growing, branching set of gameplay states and categories doesn't fit well into a C++ enum — a new value requires recompilation, and hierarchical relationships ("Status.Debuff.Stun" is a subtype of "Status.Debuff") cannot be expressed by an enum at all. FGameplayTag is a hierarchical string with fast comparison, declared as data rather than recompilable code.
Deep dive → FGameplayTag
Why are there Data Assets?
Content characteristics hardcoded in C++ or Blueprint constants (weapon damage, item weight) don't scale with a growing content list and require programmer involvement for every balance change. UDataAsset is a regular UObject, but specifically designed for data editable by a designer without recompilation and without going to a programmer.
Deep dive → UDataAsset
Why are there Primary Assets?
TSoftObjectPtr solves "don't load everything at once," but it doesn't solve "which 50 out of 3000 DataAssets are actually needed right now" — managing this through implicit chains of soft references doesn't scale. A Primary Asset is an explicit registration of a specific UObject with the Asset Manager under a stable identifier (type + name), independent of the file path, providing a single, centrally managed content loading catalog.
Deep dive → UAssetManager
💡 Senior Thoughts
When I encounter an unfamiliar engine system for the first time, I don't go read its entire API. I first ask: which of these twelve problems does it solve — and for whom does it play the role of UObject, Reflection, GC, or Component in this specific task? In nine out of ten cases, the answer is found faster than the documentation for the system itself.