Physics Trigger Volume

Base class and component for physics trigger and collision handling — inherit to create interactive volumes with enter, exit, and hold callbacks.

The physics trigger system is two classes: PhysicsTriggeringVolume (the non-component base class with all trigger logic) and PhysicsTriggerComponent (the concrete O3DE component that wraps it with game-lifecycle awareness). Inherit from either to create interactive volumes — damage zones, pickup areas, dialogue triggers, environmental hazards — without writing boilerplate physics code.

The base class handles entity tracking (one enter/exit per entity), supports both trigger overlaps and collision contacts, and provides optional hold/persist callbacks for continuous processing.

For usage guides and setup examples, see The Basics: GS_Core.

 

Contents


PhysicsTriggeringVolume

File: Physics/PhysicsTriggeringVolume.h Namespace: GS_Core Base classes: Physics::RigidBodyNotificationBus::Handler, DebugLoggingHelper

A non-component base class that manages the full lifecycle of a physics trigger or collision volume. Add it alongside your own AZ::Component via multiple inheritance.

Configuration Fields

FieldTypeDefaultDescription
EnableCollisionAsTriggerboolfalseTreat collision begin/persist/end events as trigger-style callbacks
EnableTriggerHoldUpdateboolfalseEnable per-physics-tick TriggerHold callback while entities are inside

Lifecycle Methods

MethodDescription
ConnectTriggering(AZ::EntityId entityId)Subscribes to physics events on the given entity. Call from your component’s Activate().
DisconnectTriggering()Unsubscribes and clears all handlers. Call from your component’s Deactivate().
OnPhysicsEnabled(AZ::EntityId entityId)Called when the physics body becomes active. Internally calls InitPhysicsTriggerHandler.
OnPhysicsDisabled(AZ::EntityId entityId)Called when the physics body is destroyed. Internally calls DisconnectTriggering.

Virtual Callbacks

Override these in your subclass to react to trigger and collision events.

MethodParametersReturnsDescription
TriggerEnterAZ::EntityId entityboolCalled when an entity enters the volume. Return false to reject the entity.
TriggerHoldfloat fixedDeltaTimevoidCalled each physics tick while entities are inside. Requires EnableTriggerHoldUpdate = true.
CollisionHoldAZ::EntityId entityvoidCalled per-entity each physics tick for collision events. Requires EnableCollisionAsTrigger = true.
TriggerExitAZ::EntityId entityboolCalled when an entity exits the volume. Return false to reject.

Internal State

FieldDescription
m_entitiesAZStd::unordered_set<AZ::EntityId> — entities currently inside the volume
m_triggerEntityThe entity whose physics body is being monitored

PhysicsTriggerComponent

File: Physics/PhysicsTriggerComponent.h Namespace: GS_Core Base classes: PhysicsTriggeringVolume, GameManagerNotificationBus::Handler

A concrete O3DE component that wraps PhysicsTriggeringVolume and adds game-lifecycle awareness. Automatically disables the trigger during game standby and re-enables it on exit.

Used by: WorldTriggerComponent (gs_interaction), ColliderTriggerSensorComponent — these subclass PhysicsTriggerComponent to implement game-specific trigger behaviors.

Data Fields

FieldTypeDefaultDescription
isActiveboolfalseWhether the trigger is currently armed
triggerEntityAZ::EntityIdinvalidThe entity providing the physics body to monitor

Virtual Methods

Override these to implement game-specific trigger behavior.

MethodDescription
ActivatePhysicsTrigger(AZ::EntityId entity)Called when triggered. Subclasses perform the response here.
DeactivatePhysicsTrigger()Called on exit. Subclasses clean up here.

Standby Handling

MethodDescription
OnEnterStandby()Disables the trigger when the game enters standby
OnExitStandby()Re-enables the trigger when the game exits standby

Extending Physics Trigger Volume

Use the PhysicsTriggerComponent ClassWizard template to generate a new trigger component with boilerplate already in place — see GS_Core Templates.

Inherit directly from PhysicsTriggeringVolume alongside AZ::Component for a lightweight custom trigger. Use PhysicsTriggerComponent as your base if you need the built-in standby handling.

Header (.h)

#pragma once
#include <AzCore/Component/Component.h>
#include <GS_Core/Utility/Physics/PhysicsTriggeringVolume.h>

namespace MyProject
{
    class DamageZoneComponent
        : public AZ::Component
        , public virtual GS_Core::PhysicsTriggeringVolume
    {
    public:
        AZ_COMPONENT_DECL(DamageZoneComponent);

        static void Reflect(AZ::ReflectContext* context);

    protected:
        void Activate() override;
        void Deactivate() override;

        // Trigger overrides
        bool TriggerEnter(AZ::EntityId entity) override;
        void TriggerHold(float fixedDeltaTime) override;
        bool TriggerExit(AZ::EntityId entity) override;

    private:
        float m_damagePerSecond = 10.0f;
    };
}

Implementation (.cpp)

#include "DamageZoneComponent.h"
#include <AzCore/Serialization/SerializeContext.h>

namespace MyProject
{
    AZ_COMPONENT_IMPL(DamageZoneComponent, "DamageZoneComponent", "{YOUR-UUID-HERE}");

    void DamageZoneComponent::Reflect(AZ::ReflectContext* context)
    {
        if (auto sc = azrtti_cast<AZ::SerializeContext*>(context))
        {
            sc->Class<DamageZoneComponent, AZ::Component, GS_Core::PhysicsTriggeringVolume>()
                ->Version(0)
                ->Field("DamagePerSecond", &DamageZoneComponent::m_damagePerSecond);

            if (AZ::EditContext* ec = sc->GetEditContext())
            {
                ec->Class<DamageZoneComponent>("Damage Zone", "Deals damage inside the trigger volume")
                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
                        ->Attribute(AZ::Edit::Attributes::Category, "MyProject")
                        ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game"))
                    ->DataElement(AZ::Edit::UIHandlers::Default,
                        &DamageZoneComponent::m_damagePerSecond,
                        "Damage Per Second", "Damage dealt per second while inside");
            }
        }
    }

    void DamageZoneComponent::Activate()
    {
        EnableTriggerHoldUpdate = true;  // Enable hold callbacks for continuous damage
        GS_Core::PhysicsTriggeringVolume::ConnectTriggering(GetEntityId());
    }

    void DamageZoneComponent::Deactivate()
    {
        GS_Core::PhysicsTriggeringVolume::DisconnectTriggering();
    }

    bool DamageZoneComponent::TriggerEnter(AZ::EntityId entity)
    {
        AZ_TracePrintf("DamageZone", "Entity entered damage zone");
        return true; // Accept the entity
    }

    void DamageZoneComponent::TriggerHold(float fixedDeltaTime)
    {
        // Apply damage to all entities currently inside
        for (const AZ::EntityId& entity : m_entities)
        {
            // Apply m_damagePerSecond * fixedDeltaTime damage to entity...
        }
    }

    bool DamageZoneComponent::TriggerExit(AZ::EntityId entity)
    {
        AZ_TracePrintf("DamageZone", "Entity exited damage zone");
        return true;
    }
}

Setup

  1. Create an entity with a PhysX Collider component set as a trigger.
  2. Add your custom trigger component (e.g., DamageZoneComponent).
  3. Configure the collider shape and component properties.
  4. Entities with PhysX rigid bodies that enter the collider will trigger your callbacks.

See Also

For conceptual overviews and usage guides:

For related resources:


Get GS_Core

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