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 (Blueprint subclass of UCrimsonCommonGameInstance) | GameInstanceClass in DefaultEngine.ini |
| Local player | UCrimsonCoreLocalPlayer (subclass of UCrimsonCommonLocalPlayer) | 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 | UI.Layer.Game, UI.Layer.GameMenu, HUD.Slot.* | CrimsonCore's Config/Tags ini |
| HUD push | GFA_AddWidget pushes W_CrimsonHUD_Layout (a UCrimsonHUDLayout) and fills HUD.Slot.* extension points | Experience action sets (GameFeature content) |
The GameFeature flow
GFA_AddWidget registers a GameFramework extension handler on ACrimsonHUD. 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)
- A
UCrimsonCommonGameInstancesubclass +LocalPlayerClassName(Quick Start step 2). - 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.