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

Return to the regular view of this page.

Phantom Cameras

How to configure a Phantom Camera — priority, target, lens, stage composition, and snap / focus state.

A Phantom Camera is a virtual camera definition placed in your level as a component on an ordinary entity. It does not render anything. Instead, the GS_PhantomCameraComponent holds priority, lens, target routing, and a stage pipeline slot that authors fill in to give the cam its behavior. The Cam Manager arbitrates priority across all registered Phantom Cameras in a channel — whichever active cam holds the highest priority drives the real camera at any given moment via the Cam Core.

Where previous versions of GS_PhantomCam shipped separate components for each behavior, all of those behaviors are now stage variants layered on top of the single base component. To make a cam follow, orbit, sweep along a spline, or track a group of subjects, you slot a Body stage and an Aim stage — and optionally one or more Additive stages — from the editor’s type-picker.

For architecture details, component properties, and extending the system in C++, see the Framework API reference.

Phantom Camera component in the O3DE Inspector

 

Contents


How Priority Works

Every GS_PhantomCameraComponent has a base priority. The Cam Manager continuously evaluates priority across all active Phantom Cameras in a channel and routes camera control to the highest. Influences (Influence Fields, gameplay code) can add temporary priority modifiers without touching the base value. When the dominant camera changes, the Cam Manager notifies the Cam Core to begin blending toward the new winner.

ConditionResult
Camera A priority 10, Camera B priority 5 — both activeCamera A is dominant.
Camera A is disabled or deactivatedCamera B becomes dominant immediately (or blends if a Blend Profile entry matches the A → B pair).
Camera A and Camera B both priority 10The most recently activated one is dominant.
No Phantom Cameras are active in a channelThe real camera holds its last known position.

In multi-channel projects, each channel arbitrates independently — player 1 dominance changes do not affect player 2’s view.


PhantomCamData Fields

Each Phantom Camera stores a PhantomCamData record with its lens, priority, and follow target. Follow / look-at offsets, damping halflives, and target-mode resolution live on the stages, not on PhantomCamData.

FieldTypePurpose
Prioritys32Base priority used in arbitration. Higher wins.
FOVfloatField of view in degrees. Applied to the real camera when dominant.
NearClipfloatNear clip plane distance.
FarClipfloatFar clip plane distance.
CamTargetEntityIdThe follow target. May be left empty to inherit the channel target from the Cam Manager.

A Phantom Camera with no CamTarget and no inherited channel target sits at its entity’s authored position until a target is bound.


Stage Composition

The cam’s behavior is the composition of one Body stage, one Aim stage, and zero-or-more Additive stages. Each is picked from the editor’s type-picker on the corresponding slot.

SlotCommon picksWhat it controls
BodyDefaultFollowBody, OrbitBody, DynamicOrbitBody, LeadingFollowBody, TrackBodyHow the cam follows the target.
AimDefaultLookAtAim, ClampedLookAimHow the cam orients toward the target.
Additives (Reposition)CollisionReposition, TugAimListener, TugBodyListenerPose corrections — collision pushback, magnetic spatial pulls.
Additives (Noise)PerlinNoise, ImpulseNoisePose perturbations — handheld sway, event-triggered shake.

A third-person shoulder cam, for example, slots LeadingFollowBody + DefaultLookAtAim + a CollisionReposition additive. An orbital boss cam slots DynamicOrbitBody + DefaultLookAtAim + a PerlinNoise additive for handheld feel.

For full step-by-step composition recipes, see the recipes page.

Stage Composition Recipes API

Retired components

ClampedLook_PhantomCamComponent, StaticOrbit_PhantomCamComponent, and Track_PhantomCamComponent no longer exist as separate components. Their behavior is now provided by stage variants:

Retired componentReplacement
StaticOrbit_PhantomCamComponentOrbitBody Body stage.
ClampedLook_PhantomCamComponentClampedLookAim Aim stage.
Track_PhantomCamComponentTrackBody Body stage.

AlwaysFaceCameraComponent is unchanged — it is still a billboard helper, not a camera type itself.


Channel Scope

Each Phantom Camera authors a Channel Scope that decides how it participates in the channel system. In single-player projects, leave this at the default (Local) and everything routes through channel 0. In multi-channel projects:

ScopeUse for
Local (default)The cam lives in its rig’s channel. Each spawned rig instance has its own copy.
AllChannelsIn-rig per-player broadcast cam — every spawned rig carries a duplicate.
TrueUniqueA single instance bound to a specific channel, or shared across every channel (e.g. cinematic collapse cams paired with Group Targets).

For the full walkthrough, see Channels & Instancing.


Snap and Focus

A Phantom Camera ticks each frame when any of these is true:

  • m_hasFocus — this cam is the channel’s currently-driven cam.
  • m_alwaysUpdate — authored opt-in to always tick (background-tracking cams).
  • m_blendingOut — this cam is the outgoing source of an in-flight blend.

Outside that condition the cam is fully dormant — it does not tick, its stages do not run, and its body does not integrate input.

The cam automatically snaps to its evaluated ideal pose (bypassing damping for one tick) on:

  • Focus gain.
  • A new target binding (SetCameraTarget).
  • A new group-target binding (SetTargetFocusGroup).
  • An explicit QueueSnapCamera() call.

For synchronous snap (typically only needed by framework code at mid-spawn binding), call SnapCameraNow() instead.


Activating and Deactivating Cameras

Phantom Cameras participate in priority arbitration only while their entity is active. Enable or disable the entity to add or remove a camera from the channel. The transition between dominant cameras is animated by whichever Blend Profile entry matches the outgoing → incoming pair (see Blend Profiles).

ScriptCanvas

To raise a camera’s priority and make it dominant:

Because priority is numeric, you can activate multiple cameras simultaneously and let priority values determine dominance without manually disabling others.


Requesting Camera Data

Use PhantomCameraRequestBus (addressed by the Phantom Camera entity’s ID) to read or write its configuration at runtime, query staged poses, or trigger an impulse on all ImpulseNoise additives.

ScriptCanvas


Quick Reference

NeedBusMethod / Event
Read a camera’s lens / priority dataPhantomCameraRequestBus(id)GetCameraData
Change a camera’s follow targetPhantomCameraRequestBus(id)SetCameraTarget(entityId)
Change a camera’s priorityPhantomCameraRequestBus(id)SetCameraPriority(value)
Snap the camera to its ideal next tickPhantomCameraRequestBus(id)QueueSnapCamera
Fire an impulse on all ImpulseNoise additivesPhantomCameraRequestBus(id)TriggerCameraImpulse(strength)
Make a camera dominant(entity activation)Enable the Phantom Camera entity
Remove a camera from arbitration(entity activation)Disable the Phantom Camera entity
Know when the dominant camera changesCamManagerNotificationBusSettingNewCam (channel 0) or SettingNewCamOnChannel (multi-channel)
Read a stable pose for gameplay codePhantomCameraRequestBus(id)GetStablePose — preferred over GetFinalPose for movement input

Glossary

TermMeaning
Phantom CameraA virtual camera definition that publishes a candidate pose every tick.
Stage pipelineThe fixed Body → Aim → Reposition → Noise order that each cam runs each tick.
Body stageThe component that writes state.position. One slot per cam.
Aim stageThe component that writes state.rotation. One slot per cam.
Additive stageA stackable correction or perturbation that runs after Body / Aim.
PriorityA numeric value that determines which Phantom Camera drives the real camera within its channel.
ChannelOne player viewpoint slot. Channel 0 is the implicit default for single-player.

For full definitions, see the Glossary.


See Also

For the full API, component properties, and C++ extension guide:

For related systems:


Get GS_PhantomCam

GS_PhantomCam — Explore this gem on the product page and add it to your project.

1 - Stage Composition

Concept primer for composing camera behavior from Body, Aim, and Additive stages on a single Phantom Camera component.

A Phantom Camera’s behavior is the composition of one Body stage, one Aim stage, and zero-or-more Additive stages. The same GS_PhantomCameraComponent becomes a follow cam, an orbital cam, a tracking dolly, or a third-person shoulder cam depending on what is slotted from the editor’s type-picker.

This page is a concept primer for the composition model. For step-by-step recipes (third-person shoulder cam, orbital player cam, static showcase, first-person clamped look, tracking dolly, group-framing cam) see the recipes collection.

PhantomCam Configurations (Recipes) API

For the per-variant fields and kinematic models, see the Stage Pipeline API reference.

A fully-configured Phantom Camera with body, aim, and additive stages slotted

 

Contents


The Pipeline at a Glance

Each tick, the cam runs:

Body → Aim → Reposition additives → Noise additives → Finalize
SlotWhat it doesWhen you change it
BodyWrites the cam’s position.Different follow behavior — orbit vs. spring-damped follow vs. spline-bound.
AimWrites the cam’s rotation.Different look behavior — free look vs. clamped envelope.
Reposition additivesCorrect the smoothed pose (collision pushback, magnetic tug). Run BEFORE noise.When the cam needs to avoid geometry or be pulled by spatial cues.
Noise additivesPerturb the final pose (handheld sway, event-triggered shake). Run AFTER reposition.Game feel — adding life or punch.

Each stage owns its own damping. There is no separate “smoothing” stage.


Where to Go Next

If you want to…Go here
Configure a specific cam type (shoulder, orbital, static showcase, first-person, tracking dolly, group-framing)PhantomCam Configurations
Add camera shake (handheld feel or event-triggered impact)Camera Noise Configurations and The Basics: Noise & Impulse
Pull the cam toward a vista pointCamera Tug Configurations and The Basics: Tug Fields
Frame multiple subjectsGroup Target Configurations and The Basics: Group Targets
See the full per-variant kinematic modelFramework API: Stage Pipeline

See Also

Recipes for stage composition:

For the full per-variant API and kinematic models:

Related basics pages:


Get GS_PhantomCam

GS_PhantomCam — Explore this gem on the product page and add it to your project.

2 - Noise & Impulse

Author guide for camera shake — the two noise additive stages, preset library, gameplay-code impulse triggering, and the Stable-vs-Final pose readback rule.

Camera shake comes in two flavors, both as Noise additives on a Phantom Camera’s stage list:

  • PerlinNoise — continuous Perlin-noise displacement. Use for handheld feel, idle sway, low-frequency wobble. Always sampling.
  • ImpulseNoise — event-triggered burst, gated by an ADSR envelope. Use for explosions, foot-stomps, gun kicks. Stays silent until you fire it.

Both consume the same .camnoiseprofile asset and the same six-axis Perlin layer model. Stack freely on the same cam — a baseline handheld profile plus an event-triggered impact profile is the canonical combination.

For step-by-step composition recipes (handheld baseline, event-triggered impact, stacked handheld + impact), see the recipes collection.

Camera Noise Configurations (Recipes) API

For the asset reference and per-axis layer details, see Noise Profiles (Framework API). For the stage variants’ authored fields and kinematic models, see Additive Stage Variants (Framework API).

 

Contents


Preset Library

A starter library of .camnoiseprofile assets ships in gs_phantomcam/Assets/Noise Profiles/. Drop one onto a PerlinNoise or ImpulseNoise stage’s Profile slot to get an immediate baseline. Match the preset’s lens family to the cam’s lens for natural feel.

Handheld lens family — pair with PerlinNoise

AssetLens character
Normal_Mild.camnoiseprofileNormal-lens baseline. Balanced position and rotation.
Normal_Intense.camnoiseprofileNormal-lens active handheld. Larger amplitudes.
Telephoto_Mild.camnoiseprofileTelephoto baseline. Tighter angular response, low position.
Telephoto_Intense.camnoiseprofileAggressive telephoto handheld.
Wide_Mild.camnoiseprofileWide-lens baseline. Translation dominates; rotation low.
Wide_Intense.camnoiseprofileAggressive wide-lens handheld.

All-axes shake family — pair with ImpulseNoise or aggressive PerlinNoise

AssetCharacter
6D_Shake.camnoiseprofileEarthquake / impact aftermath — all six axes, high-frequency micro-jitter on top of mid-frequency sway.
6D_Wobble.camnoiseprofileFloaty / dreamlike — all six axes, low-frequency long sway.

Tuning intensity without re-authoring

Per-cam intensity is dialed on the additive stage’s AmplitudeGain (and FrequencyGain for speed). A single Normal_Mild profile can drive a subtle cutscene cam (AmplitudeGain = 0.3) and a frantic chase cam (AmplitudeGain = 1.8) without authoring new assets.

For project-specific characters — gunfire-tuned impulse profiles, ultra-mild cinematic sway, etc. — see Authoring a Custom Profile.


Triggering an Impulse from Gameplay Code

Fire TriggerCameraImpulse(strength) on the cam to play one burst of every ImpulseNoise additive on it.

C++

#include <GS_PhantomCam/Cameras/GS_PhantomCameraBus.h>

// Compute distance-based falloff.
const float strength = AZ::GetClamp(1.0f - distance / radius, 0.0f, 1.0f);

GS_PhantomCam::PhantomCameraRequestBus::Event(
    activeCameraEntityId,
    &GS_PhantomCam::PhantomCameraRequests::TriggerCameraImpulse,
    strength);

strength multiplies each stage’s AmplitudeGain for that specific burst. Pass 1.0 for full profile intensity, smaller for distance falloff, larger to boost.

Author pattern: distance-attenuated impact source

A typical “explosion at world position X” pattern:

const float distance     = (explosionPos - cameraPos).GetLength();
const float falloff      = AZ::GetClamp(1.0f - distance / kEffectRadius, 0.0f, 1.0f);
const float baseStrength = 1.5f;       // for the explosion's overall punch

const float impulseStrength = baseStrength * falloff;

GS_PhantomCam::PhantomCameraRequestBus::Event(
    activeCamId,
    &GS_PhantomCam::PhantomCameraRequests::TriggerCameraImpulse,
    impulseStrength);

Cams outside kEffectRadius receive strength = 0 and ignore. Cams at the explosion’s exact position receive full baseStrength.

Querying the active cam

TriggerCameraImpulse is per-cam, so you need a target cam id. The common pattern is to track the channel’s currently-active cam via SettingNewCam / SettingNewCamOnChannel and store it, or query CamManagerRequestBus::GetActiveCamCore() for the engine’s active view.


Stable vs Final Pose for Gameplay Readback

Cam pose snapshots come in three flavors:

SnapshotWhere it landsUse it for…
Desired posePost Body + Aim, pre-Reposition. Clean ideal.Debug visualization.
Stable posePost Reposition, pre-Noise. Collision-corrected but shake-free.Gameplay code that reads camera facing (e.g. movement-input direction).
Final posePost Noise. What gets rendered.Audio listener, screen-space UI.

The pitfall. If your character moves “where the camera is facing,” and you read GetFinalPose (or the entity’s TransformBus), every shake event will momentarily drag the character around. Use GetStablePose instead — the cam’s pose without noise displacement.

AZ::Transform stable;
GS_PhantomCam::PhantomCameraRequestBus::EventResult(
    stable,
    activeCamId,
    &GS_PhantomCam::PhantomCameraRequests::GetStablePose);

const AZ::Vector3 cameraForward = stable.GetBasisY();   // O3DE forward axis

Authoring a Custom Profile

Camera Noise Profile asset in the O3DE Asset Editor

When the shipped presets don’t fit, author your own:

  1. Open the Asset Editor in O3DE.
  2. Select New and choose CameraNoiseProfile.
  3. For each axis where you want noise (typically translation X / Y and rotation pitch / yaw / roll), add 1–3 layers. Three layers per axis is the typical rhythm: one slow / large layer for sway, one mid layer for flutter, one fast / small layer for micro-jitter.
  4. For each layer set:
    • Amplitude — in meters (position) or degrees (rotation).
    • Frequency — in Hz. Handheld typically 0.1 – 2 Hz; shake / impact 3 – 60 Hz.
    • Phase (optional) — decorrelates layers that share frequency.
  5. Set the Description to record intent and tuning history.
  6. Save the asset.
  7. Assign it to a PerlinNoise or ImpulseNoise additive stage’s Profile slot.

See Noise Profiles (Framework API) for the full per-field reference.


See Also

Recipes:

Framework API:

Related basics pages:


Get GS_PhantomCam

GS_PhantomCam — Explore this gem on the product page and add it to your project.