This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Channel Tier Configurations

Step-by-step walkthroughs for the PhantomCam channel system — Tier 1 single cam, Tier 2 level-placed, Tier 3 multi-channel co-op, common Tier 3 patterns, and the lobby flow for variable player counts.

GS_PhantomCam can be configured at three different tiers depending on what your project needs. Most projects use Tier 1 (single-cam) or Tier 2 (single-player rig). Co-op, split-screen, and per-player-cinematic projects use Tier 3 (multi-channel). The per-cam authoring surface is identical across tiers — what changes is the Cam Manager configuration and how many rigs the system spawns.

For the concept of channels, the choose-a-tier table, and pitfalls, see The Basics: Channels & Instancing. For the full bus surface and internal state, see Channels & Instancing (Framework API).

Multi-view rendering is pending. Until the AttachmentImage work lands, the engine renders one channel’s view at a time even when multiple channels are arbitrating internally. The Cam Manager’s active main-view API selects which channel reaches the framebuffer. Arbitration / dispatch / target binding all work today — only the simultaneous-rendering piece is gated.

Authored rig prefab in the O3DE Editor

 

Contents


Recipe: Tier 1 — Single Cam

The Cam Manager spawns one rig prefab on startup, and every Phantom Camera inside it registers to channel 0.

Steps

  1. Author a rig prefab. Create a prefab containing:

    • A root entity (anything — it can be empty, or a logical “Camera Rig” entity).
    • A child entity carrying GS_CamCoreComponent plus the engine’s standard CameraComponent. This is the main camera.
    • Zero or more child entities carrying GS_PhantomCameraComponent with their authored Body / Aim stages.
  2. On the Cam Manager component:

    • Set Primary Rig Prefab to your rig prefab.
    • Leave Enable Instanced Channels OFF (default).
  3. Bind a target when the player spawns:

    CamManagerRequestBus::Broadcast(SetTarget, playerEntity);
    
  4. The Cam Manager spawns the rig at startup. The rig’s Cam Core and Phantom Cameras self-register to channel 0. The SettingNewCam legacy notification fires when the dominant cam changes.

That’s it. No further per-cam setup required.


Recipe: Tier 2 — Single-Player Rig (Legacy)

Same single-player behavior, but the Cam Core lives in the level rather than in a spawned prefab. Use this when you have an existing project that hand-places the Cam Core and you don’t want to refactor.

Steps

  1. Hand-place the Cam Core entity in your level (as a child of the Cam Manager prefab, or any persistent entity).
  2. On the Cam Manager:
    • Leave Primary Rig Prefab empty.
    • Leave Enable Instanced Channels OFF.
  3. Bind a target as in Tier 1.

The level-placed Cam Core and Phantom Cameras self-register to channel 0 via the legacy bus path (no ChannelStampComponent ancestor, so the stamp walk misses and the legacy registration falls through).


Recipe: Tier 3 — Multi-Channel Co-op

The Cam Manager spawns one rig per active channel. Each channel arbitrates independently. Per-player target binding routes through SetChannelTarget.

Steps

  1. Author your rig prefab as in Tier 1. The same prefab can be reused across all channels (symmetric setup) or you can author multiple prefabs for asymmetric setups (e.g. P1 third-person, P2 top-down).

  2. On the Cam Manager:

    • Toggle Enable Instanced Channels ON. The channel-aware fields appear in the inspector.

    • Set Primary Rig Prefab to your default rig (used as universal fallback — channels with no per-channel override inherit this).

    • Populate Channel Configs with one entry per supported player slot:

      FieldSet to
      Channel Name"P1", "P2", etc. (display label only — not a lookup key).
      Channel PolicyPerChannelInstance (default — the rig spawns once per channel).
      Rig Override PrefabLeave empty for symmetric (every channel uses the primary). Set to a per-channel prefab for asymmetric.
      Enabled By Defaulttrue for slots that should spawn on startup.
    • Optionally set Active Channel Count to cap how many channels actually spawn at startup (the lobby may override this — see Lobby Flow).

  3. Per-player target binding — when each player spawns:

    CamManagerRequestBus::Broadcast(SetChannelTarget, channelId, playerEntity);
    

    The Cam Manager pushes the target to every cam in that channel and triggers a synchronous snap so the cam jumps to its evaluated pose before the Cam Core latches.

  4. The Cam Manager spawns each enabled channel’s rig at startup. Each rig’s Cam Core registers to its channel; each Phantom Camera walks its ancestors to find the auto-attached ChannelStampComponent and registers to the same channel.


Common Tier 3 Patterns

Per-player cam (in-rig)

Drop a Phantom Camera inside the rig prefab with m_channelScope = Local (default). When the rig spawns for channel N, the cam’s auto-stamp-walk finds the rig’s ChannelStampComponent and registers to channel N. Each spawned rig instance carries its own copy — players don’t see each other’s cams.

Same logical cam name across channels

Keep entity names like "third_person_rig_cam" inside the rig prefab. The name is scoped within the channel — channel 0 and channel 1 each have their own "third_person_rig_cam" and they don’t collide. Authors never type _i1 / _i2 suffixes.

Shared cinematic cam — collapse-to-one-view

Author a Phantom Camera outside any rig prefab (in the level, or in a “shared cinematic” prefab that is not the channel rig). Set:

  • Channel ScopeTrueUnique.
  • Show Advanced → on.
  • All Channels Share → on.

The cam appears in every active channel’s priority table. When players converge (e.g. a Group Target tracks all players and the shared cam targets the group), the shared cam may win arbitration in every channel simultaneously. At that edge, the Cam Manager broadcasts OnAllChannelsActivatedSharedCam(sharedCam) — UI can detect this and switch from split-screen layout to single-view. See the Collapse to Single View recipe for the group-target side.

Hero-perspective cam for a specific player

A cam that should only ever apply to one specific channel:

  • Channel ScopeTrueUnique.
  • Bound Channel Id → the channel number (e.g. 0 for P1).
  • Leave All Channels Share off.

The cam is registered directly to that channel via RegisterPhantomCamDirect — bypasses the stamp-walk path entirely.

Cross-channel cinematic dispatch

Force a specific cam to render on a specific Cam Core, regardless of arbitration:

CamManagerRequestBus::Broadcast(DispatchCamToCamCore, cinematicCamEntity, p1CamCore);
// ... cinematic plays ...
CamManagerRequestBus::Broadcast(ReleaseCamCoreDispatch, p1CamCore);

Channel arbitration still runs internally during dispatch — SettingNewCamOnChannel continues firing with the arbitrated winner. Only the Cam Core route is overridden, so HUD or AI behavior that listens for arbitration changes still sees the “natural” winner.


Lobby Flow

The typical lobby pattern for variable player counts:

  1. Author m_channelConfigs to hold N entries (the max supported player count for your project — e.g. 4).

  2. Pre-startup (before the Cam Manager’s OnStartupComplete fires), the lobby calls:

    CamManagerRequestBus::Broadcast(SetActiveChannelCount, actualPlayerCount);
    
  3. On startup, only actualPlayerCount channels spawn. The remaining configured channels stay dormant.

  4. Mid-session join / drop uses EnableChannel(channelId) / DisableChannel(channelId) to spawn or despawn channels as players come and go.

SetActiveChannelCount must run pre-startup. Mid-session calls warn and are ignored — use EnableChannel / DisableChannel instead.


See Also

Related recipe collections:

Basics this builds on:

Framework API: