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

Return to the regular view of this page.

Group Targets

GroupTargetComponent — weighted-centroid focal entity. Computes a centroid from a subject list and writes it to its own transform. Phantom Cameras point at it like any other target.

A Group Target is an entity whose world transform is the weighted centroid of a runtime-editable subject set. Phantom Cameras with CamTargetMode::GroupTarget point at it like any other target. The Cam Manager hosts a global name → entity registry so stages can resolve a group entity by string name without holding a direct reference.

Typical use cases:

  • Two-player co-op — a group target tracks both players; the cam follows the group target.
  • “Move when group is contained” cinematic cams — frame all subjects, ignore individual wandering.
  • Combat encounters with multiple participants — track the weighted centroid of all combatants.
  • Collapse-to-single-view in multi-channel projects — pair with a shared TrueUnique cam to detect when all channels converge.

GroupTargetComponent in the O3DE Inspector

 

Contents


Registry Pattern

The Cam Manager owns a global name → entity registry for group targets.

On GroupTargetComponent::Activate:

CamManagerRequestBus::Broadcast(
    &CamManagerRequests::RegisterGroupTarget,
    m_name,
    GetEntityId());

On Deactivate:

CamManagerRequestBus::Broadcast(
    &CamManagerRequests::UnregisterGroupTarget,
    GetEntityId());

Stages resolve a group entity via:

AZ::EntityId groupEntity;
CamManagerRequestBus::BroadcastResult(
    groupEntity,
    &CamManagerRequests::FindGroupTargetByName,
    "MyGroup");

The editor dropdown for m_groupTargetName on Body / Aim stages populates from GetRegisteredGroupTargetNames.

See Cam Manager — Group Target Registry for the manager-side bus.


Evaluation Cadence

The component picks one of two cadences automatically:

CadenceWhenWhy
PhysX post-simulateAny enabled subject is physics-driven (has a RigidBodyRequestBus handler)Ensures the centroid uses post-simulate positions — no lag against physically-moving subjects.
TickBusNo physics subjectsSimple per-frame evaluation.

Cadence is re-evaluated on every subject mutation (AddSubject, RemoveSubject, SetSubjectEnabled). m_boundToPostSim / m_boundToTick track the current binding.


Centroid Modes

enum class CentroidMode : AZ::u8 {
    WeightedMean,            // Σ(pos · weight) / Σ(weight)
    BoundingBoxCenter,       // (min + max) / 2 of axis-aligned bbox, biased toward weighted mean
    BoundingSphereCenter,    // Welzl-style sphere center, biased toward weighted mean
};

The bounding modes blend toward the weighted mean by m_weightBias[0, 1]:

  • m_weightBias = 0 — pure geometric center.
  • m_weightBias = 1 — pure weighted mean.
  • Intermediate values produce a weighted-biased geometric center.

This lets weights still influence the framing point even when the geometric extent (bbox / sphere) is what really defines the group’s spread.


Orientation Modes

enum class OrientationMode : AZ::u8 {
    Identity,                  // group entity stays at identity rotation
    SpreadAxis,                // forward axis points along the long axis of subjects' spread
    WeightedAverageForward,    // weighted-average of subjects' forward vectors
};

m_publishOrientation is the master toggle. If false, the group entity stays at identity rotation regardless of mode.


Authored Fields

FieldDefaultPurpose
m_name""Registry key. Authored once; stages reference by this name. Empty = unregistered.
m_subjects{}List of GroupSubject rows.
m_modeWeightedMeanCentroid mode.
m_weightBias0.0When mode is not WeightedMean: blend factor toward weighted mean.
m_smoothingHalflife0.0Optional centroid damping (0 = no smoothing).
m_publishOrientationfalseWhether to write rotation to the group entity.
m_orientationModeSpreadAxisRotation derivation (when publishOrientation enabled).
m_deactivateWhenEmptytrueIf true and m_subjects becomes empty, the group entity stops ticking — cam bodies see “no target” and fall back to hold-last pose.

GroupSubject Struct

struct GroupSubject {
    AZ::EntityId  m_entity;
    float         m_weight  = 1.0f;
    AZ::Vector3   m_offset  = (0, 0, 0);   // applied to subject's world pos
    bool          m_enabled = true;
};

Each subject carries an offset and an enabled flag. Toggling m_enabled lets gameplay code temporarily exclude a subject without removing it from the list (cheaper than RemoveSubject + AddSubject since cadence rebind is suppressed).


Request Bus

GroupTargetRequestBus — per-entity addressed (the group’s own entity id).

Subject management

MethodUse
AddSubject(entity, weight)Add with default offset.
AddSubjectWithOffset(entity, weight, offset)Add with custom offset.
RemoveSubject(entity)Remove.
SetSubjectWeight(entity, weight)Adjust weight.
SetSubjectEnabled(entity, enabled)Toggle without removing from list.
ClearSubjects()Remove all.
GetSubjectEntities()Returns list of EntityIds.

Mode and smoothing

MethodUse
SetCentroidMode(mode)Runtime mode swap.
SetWeightBias(bias)Adjust bias.
SetSmoothingHalflife(halflife)Adjust smoothing.
SetPublishOrientation(enabled)Toggle rotation publishing.
SetOrientationMode(mode)Runtime orientation mode swap.

Query / diagnostics

MethodUse
GetCurrentCentroid()Last evaluated centroid (post-smoothing if enabled).
IsEvaluatingPostSim()Diagnostic — returns true if currently bound to PhysX post-sim.

Cadence-affecting mutations (AddSubject, RemoveSubject, SetSubjectEnabled) automatically call RebindEvaluationCadence.


Evaluation Algorithm

EvaluateCentroid(deltaTime):

    Collect (pos, weight) for every enabled subject:
        pos    = subject.entity.worldTM.translation + subject.offset
        weight = subject.weight

    Compute centroid by mode:
        WeightedMean         → Σ(pos · weight) / Σ(weight)
        BoundingBoxCenter    → lerp((min + max) / 2,  weightedMean, m_weightBias)
        BoundingSphereCenter → lerp(welzlCenter,      weightedMean, m_weightBias)

    If m_smoothingHalflife > 0:
        alpha = HalflifeAlpha(m_smoothingHalflife, deltaTime)
        m_lastCentroid = lerp(m_lastCentroid, centroid, alpha)
    Else:
        m_lastCentroid = centroid

    If m_publishOrientation:
        rotation = ComputeOrientation(positions, weights)
    Else:
        rotation = Identity

    Write (m_lastCentroid, rotation) to GetEntityId()'s TransformBus.

Cam-Side Usage

A Phantom Camera body or aim stage authored with m_targetMode = CamTargetMode::GroupTarget sets m_groupTargetName to the group’s registered name. At runtime, the stage resolves the group entity via the Cam Manager registry:

// In the stage's ResolveTarget or StageHelpers::ResolveStageTargetTM:
AZ::EntityId groupEntity;
CamManagerRequestBus::BroadcastResult(
    groupEntity,
    &CamManagerRequests::FindGroupTargetByName,
    m_groupTargetName);

return groupEntity;   // body / aim then reads this entity's world TM as the target

The same pattern applies to Body stages (for follow) and Aim stages (for look-at) — each can independently target a group.


Pairing with Shared Cams

A GroupTargetComponent paired with a shared TrueUnique cam (see Channels & Instancing — Cam Channel Scope) is the canonical “collapse to one view” trigger:

  • The group target tracks all players.
  • The shared cam targets the group entity.
  • When all rigs / channels select the shared cam (typical at convergence radius), OnAllChannelsActivatedSharedCam(sharedCam) fires once on the Cam Manager notification bus.
  • UI switches from split-screen to single-view layout.

See Channels & Instancing — Shared Cams and Collapse Detection for the collapse-detection details.


See Also

Related PhantomCam pages:

Basics-side authoring guide:


Get GS_PhantomCam

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