Concept: Full-Stack Integration & Multiplayer
Standalone, you boot the stack yourself (Quick Start). On the full Crimson stack, CrimsonCore ships the concrete pieces and drives them through GameFeatures - none of the types below live in CrimsonUI, but knowing them explains 'why does this already work' on the full stack.
What CrimsonCore pre-wires
| Quick Start step | CrimsonCore ships | Where |
|---|---|---|
| Game instance | B_CrimsonGameInstance (CrimsonCore's game instance; any class works) | GameInstanceClass in DefaultEngine.ini |
| Local player | UCrimsonCoreLocalPlayer (CrimsonCore's local player; any class works) | LocalPlayerClassName in DefaultEngine.ini |
| Viewport client | the CrimsonUI class directly | GameViewportClientClassName |
| Policy + root layout | B_CrimsonGameUIPolicy + a root layout with all standard layers registered | DefaultUIPolicyClass in DefaultGame.ini |
| Layer/slot tags | HUD.Slot.* (the UI.Layer.* tags are native to CrimsonUI) | CrimsonCore's Config/Tags ini |
| HUD push | UCrimsonGameFeatureAction_AddWidget (CrimsonUI) pushes W_CrimsonHUD_Layout (a UCrimsonHUDLayout) and fills HUD.Slot.* extension points | Experience action sets (GameFeature content) |
The GameFeature flow
UCrimsonGameFeatureAction_AddWidget (CrimsonUI) registers a GameFramework extension handler on the HUD class named by its HUDClass property - any AHUD, defaulting to all of them. When the HUD actor spawns on a client, the action resolves the local player and (a) pushes each configured layout class onto its UI.Layer.* layer via UCrimsonUIExtensions::PushContentToLayer_ForPlayer, and (b) registers each configured widget at its HUD.Slot.* extension point. Deactivating the feature pops and unregisters everything. This is why ACrimsonHUD (or a subclass) is required on the full stack: it is the anchor GameFeatures extend.
Multiplayer & authority
| Concern | Where it runs | Networking |
|---|---|---|
| Layouts, layers, pushes, dialogs | Owning client only | None - a dedicated server has no local players and creates zero UI |
| HUD state sources (health, tags, inventory) | Server-authoritative gameplay systems | Replicated to the client; UI reads the replicated state |
UCrimsonTaggedWidget tag checks | Client-side ASC (from the replicated PlayerState) | Tags replicate via GAS; the widget just listens |
| Player-triggered actions from UI (buy, drop, use) | UI calls into gameplay code | Route through Server_ RPCs with _Validate or GAS abilities - never mutate authoritative state directly from a widget |
| Touch input injection | Owning client's Enhanced Input | Consequences replicate through normal movement/ability channels |
Standalone checklist (what you own without CrimsonCore)
- Nothing for the game instance or local player - any class works.
- Layer tags beyond the native ones (
UI.Layer.Game,UI.Layer.GameMenu, anyHUD.Slot.*). - The policy + root layout Blueprints and
UCrimsonUISettingsentries. - Your own HUD push (PlayerController BeginPlay, GameMode, or your own GameFeature action).
- Dialog widget classes if you use the messaging subsystem.