How-To: Show Multiple Characters
Goal: put more than one character on the loading screen - the local player plus their party, their co-op partner, an escorted NPC, whatever your game means by "who is loading with me".
The loading screen presents a roster: the local player at index 0, then every companion you registered, in registration order. The plugin has no party concept at all. It renders whoever was registered, and your own party, lobby or co-op glue decides who that is and owns their lifetime.
1. Register a companion
A companion registration is the same FCrimsonLoadingCharacterInfo as the primary, filed under a key you choose. Build it exactly as you build the primary - through ICrimsonLoadingCharacterProvider on whatever owns that character's appearance data - and hand it to Add Showcase Companion.
Where this runs: on the machine whose loading screen it is, and nowhere else. A roster is a local cosmetic cache on that machine's game instance; nothing authoritative is touched and nothing replicates. Getting a remote player's appearance data to this machine in the first place is your game's job - read it from whatever already replicates for that character.
In your party or lobby Blueprint: build the struct the same way as the primary, then Get CrimsonLoadingScreenManager -> Add Showcase Companion with Companion Id (a name you choose, such as the player's unique id) and Character Info. Use Remove Showcase Companion with the same id to drop it, Clear Showcase Companions to drop them all, and Get Cached Showcase Roster to read back what the current load is presenting.
| Manager call | Effect |
|---|---|
UpdateCachedCharacterInfo(Info) | Registers the primary - the local player, roster index 0 |
AddShowcaseCompanion(CompanionId, Info) | Adds a companion, or replaces one already filed under that id |
RemoveShowcaseCompanion(CompanionId) | Drops one companion; unknown ids are ignored |
ClearShowcaseCompanions() | Drops every companion, leaving the primary |
ClearCachedCharacterInfo() | Drops the primary and every companion |
GetCachedShowcaseRoster() | What this load is presenting: primary first, companions in registration order |
Showcase companion [<your id>] registered: N mesh component(s), M additional actor(s). K companion(s) registered. Force a screen and Get Cached Showcase Roster returns more than one entry.2. Know the rules the roster enforces
- `CompanionId` is your key. Adding the same id again replaces that look in place and keeps its position in the roster, so a gear update mid-load never shuffles the formation.
- An invalid `Character Info`, or a `None` id, is ignored. Same rule as the primary: a premature call can never clobber a good registration.
- No primary means no roster. A companion standing alone is a character the player does not recognize as theirs, which is exactly what the registration rule exists to prevent - so the roster stays empty until a valid primary is registered.
- The roster is clamped to the
MaxShowcaseCharacterssetting (default 8). The primary is always first, so companions past the limit are dropped rather than crowding the shot. - Companions persist across travel, exactly like the primary, until you remove them. The registration lives on the game instance.
- Entries with no valid leader mesh are skipped when the stage builds, and the count is logged.
3. Handle players who register late
Players in the same load finish registering at different times - somebody's pawn replicates a moment after the screen went up. Registering a new companion id while the loading screen is already showing rebuilds the roster and fires On Showcase Roster Changed; the built-in showcase applies the new roster and re-frames immediately.
Replacing an existing id deliberately does not rebuild: that is the same character re-registering as its equipment replicates in, and rebuilding for it would churn the stage with nothing new to show. Registering the primary never rebuilds either - the primary is the snapshot the screen started with.
Get CrimsonLoadingScreenManager -> Bind Event to On Showcase Roster Changed -> a Custom Event with a Roster array input. Bind it from something that outlives travel - a GameInstance subclass or a game-instance subsystem. You only need this if you present the roster yourself; the built-in showcase already listens.
Showcase roster changed while the loading screen is up: N character(s). and the extra character appears in the capture.4. Decide where they stand
Placement is chosen per load, and it is all or nothing:
| Situation | What happens |
|---|---|
The stage level has at least as many ACrimsonShowcaseSlot actors as characters | Slots are sorted by SlotIndex and character i stands on slot i, in that slot's world transform and facing |
| No slots, or too few | The procedural formation places everyone, and a warning names both counts |
The procedural formation is a clustered group photo, not a line. The primary stands center-front; everyone else alternates right and left, one small lateral step further out each time, and each step drops into either the back row or the front row so nobody stands in the way of the character behind them. With eight characters the front row sits at Y = 0, +/-150 and +300 cm and the back row fills the gaps at Y = +/-75 and +/-225 cm. Each step also yaws a few degrees toward the center, and a small per-step arc walks both rows back as the group widens. Tune it on the stage with FormationLateralStep, FormationRowDepth, FormationFrontRowInset, FormationArcDepthPerStep and FormationYawPerStep. The turntable only spins when exactly one character is shown and the formation placed it - a rotating group reads as a carousel, and a character rotating inside authored set dressing turns its back on the set.
placed by level slots. Remove a slot and it says placed by formation, preceded by the too-few-slots warning.5. Frame the group
Framing follows the head count. The stage looks for an ACrimsonShowcaseCamera whose CharacterCount equals the number of characters on stage, then for one with CharacterCount == 0, and only then falls back to its own built-in direction. Every case except a camera with bAutoFit unticked auto-fits: the stage combines each mesh asset's bounds, aims at the center of that box, and slides along the view axis to the smallest distance at which all eight corners sit inside the frame, times FramingPadding. The vertical field of view comes from the render target's aspect ratio.
CharacterCount = 1 and another with CharacterCount = 0, then change the head count: the one-character shot is used for a solo load and the any-count shot for the rest.6. Test it with one player
CrimsonLoadingScreen.Showcase.DebugCompanions N duplicates the registered primary N times into the roster at show time, so slot placement and framing can be exercised without a second machine. It is clamped by MaxShowcaseCharacters like everything else. Pair it with CrimsonLoadingScreen.AlwaysShow 1 to hold the screen while you look.
CrimsonLoadingScreen.AlwaysShow 1CrimsonLoadingScreen.Showcase.DebugCompanions 3; ... look at the screen, then:CrimsonLoadingScreen.Showcase.DebugCompanions 0CrimsonLoadingScreen.AlwaysShow 0
See also
- How-To: Showcase the Player's Character - describing and registering the primary.
- How-To: Author a Stage Level - placing the slots and the shots.
- How-To: Control the Screen Per Load (optional) - suppressing the showcase for a specific load.
- API Reference -> UCrimsonLoadingScreenManager - the exact roster signatures.