Physics Trigger Volume
Categories:
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
| Field | Type | Default | Description |
|---|---|---|---|
EnableCollisionAsTrigger | bool | false | Treat collision begin/persist/end events as trigger-style callbacks |
EnableTriggerHoldUpdate | bool | false | Enable per-physics-tick TriggerHold callback while entities are inside |
Lifecycle Methods
| Method | Description |
|---|---|
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.
| Method | Parameters | Returns | Description |
|---|---|---|---|
TriggerEnter | AZ::EntityId entity | bool | Called when an entity enters the volume. Return false to reject the entity. |
TriggerHold | float fixedDeltaTime | void | Called each physics tick while entities are inside. Requires EnableTriggerHoldUpdate = true. |
CollisionHold | AZ::EntityId entity | void | Called per-entity each physics tick for collision events. Requires EnableCollisionAsTrigger = true. |
TriggerExit | AZ::EntityId entity | bool | Called when an entity exits the volume. Return false to reject. |
Internal State
| Field | Description |
|---|---|
m_entities | AZStd::unordered_set<AZ::EntityId> — entities currently inside the volume |
m_triggerEntity | The 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
| Field | Type | Default | Description |
|---|---|---|---|
isActive | bool | false | Whether the trigger is currently armed |
triggerEntity | AZ::EntityId | invalid | The entity providing the physics body to monitor |
Virtual Methods
Override these to implement game-specific trigger behavior.
| Method | Description |
|---|---|
ActivatePhysicsTrigger(AZ::EntityId entity) | Called when triggered. Subclasses perform the response here. |
DeactivatePhysicsTrigger() | Called on exit. Subclasses clean up here. |
Standby Handling
| Method | Description |
|---|---|
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.
public virtual inheritance with PhysicsTriggeringVolume to avoid issues with multiple inheritance chains that include AZ::Component.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
- Create an entity with a PhysX Collider component set as a trigger.
- Add your custom trigger component (e.g.,
DamageZoneComponent). - Configure the collider shape and component properties.
- 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.