GS_Actions
A utility system for triggerable single-purpose actions — fire discrete behaviors from any system without recoding logic for each component.
Overview
The Actions system provides a simple, universal pattern for triggering discrete behaviors. Instead of recoding common functionality (toggle cursor, play sound, print log) into every component that needs it, you attach Action components to an entity and fire them by channel name.
Actions support chaining — when one action completes, it can fire another action on a different channel, enabling lightweight sequences without custom code.
Architecture
Entity with Actions
│
├── ToggleMouseCursor_GSAction (channel: "enter_menu")
├── PlaySound_GSAction (channel: "enter_menu")
└── PrintLog_GSAction (channel: "debug")
Any system calls:
ActionIncomingEventBus::Event(entityId, DoAction, "enter_menu")
→ Both ToggleMouseCursor and PlaySound fire (matching channel)
→ PrintLog does NOT fire (different channel)
Components
| Component | Purpose | Documentation |
|---|
| GS_ActionComponent | Base class for all actions. Handles channel matching, completion broadcasting, and action chaining. | Action |
| ToggleMouseCursor_GSActionComponent | Toggles the mouse cursor on or off. | Core Actions |
| PrintLog_GSActionComponent | Prints a message to the console log. | Core Actions |
Quick Start
- Attach one or more Action components to an entity.
- Set the Channel on each action to control when it fires.
- From any system, call
DoAction(channelName) on the entity’s ActionIncomingEventBus to trigger matching actions. - Optionally enable Broadcast On Complete and set an On Complete Channel Chain for action sequencing.
See Also
1 - Action
The base class for triggerable actions — channel-based firing, completion broadcasting, and action chaining for lightweight behavior sequencing.
Overview
GS_ActionComponent is the base class for all triggerable actions. Actions are single-purpose behaviors that fire when their channel matches an incoming DoAction call. They support completion broadcasting and optional chaining to sequence multiple actions together.
Every GS_Play action (Toggle Mouse Cursor, Print Log, and actions from other gems) extends this class. When you need a custom action, you extend it too.
How It Works
Firing an Action
- A system calls
DoAction(targetChannel) on an entity’s ActionIncomingEventBus. - Every Action component on that entity evaluates whether its channel matches the
targetChannel. - Matching actions call
ProcessAction() to execute their behavior. - When done,
CompleteAction() handles completion:- If Broadcast On Complete is enabled, it fires
OnActionComplete on the ActionOutgoingEventBus. - If On Complete Channel Chain is set, it fires a new
DoAction with that channel name, triggering the next action in the chain.
Chaining Actions
By setting the On Complete Channel Chain to a different channel name, an action can trigger the next step in a sequence when it completes. This enables lightweight behavior chains without custom sequencing code.
Action A (channel: "step1", onCompleteChain: "step2")
→ fires → Action B (channel: "step2", onCompleteChain: "step3")
→ fires → Action C (channel: "step3")
Important: Every custom action must call CompleteAction() when its work is done. If you forget, the action will never complete and chains will break.
Inspector Properties
| Property | Type | Default | Description |
|---|
| Channel | AZStd::string | "" | The channel this action responds to. Only DoAction calls with a matching channel will trigger this action. |
| Broadcast On Complete | bool | false | When enabled, broadcasts OnActionComplete on the ActionOutgoingEventBus when this action finishes. |
| On Complete Channel Chain | AZStd::string | "" | When non-empty, fires a new DoAction with this channel name after completing. Enables action chaining. |
API Reference
Request Bus: ActionIncomingEventBus
Entity-addressed bus — call via Event(entityId, ...).
| Method | Parameters | Returns | Description |
|---|
DoAction | AZStd::string targetChannel | void | Triggers all actions on the target entity whose channel matches targetChannel. |
Notification Bus: ActionOutgoingEventBus
Entity-addressed bus — connect via BusConnect(entityId).
| Event | Parameters | Description |
|---|
OnActionComplete | — | Broadcast when an action with Broadcast On Complete enabled finishes its work. |
Local / Virtual Methods
Override these when creating custom actions.
| Method | Description |
|---|
DoAction(targetChannel) | Evaluates whether this action should fire. Default compares channel to targetChannel. Override for custom evaluation logic. |
ProcessAction() | Your primary override. Executes the action’s behavior. Called when channel evaluation passes. |
CompleteAction() | Handles completion. Default checks broadcastOnComplete, fires OnActionComplete, then checks onCompleteChannelChain for chaining. Override to add custom completion logic, but always call base or handle chaining manually. |
Usage Examples
Firing Actions on an Entity
#include <GS_Core/GS_CoreBus.h>
// Fire all actions on this entity that match the "open_door" channel
GS_Core::ActionIncomingEventBus::Event(
targetEntityId,
&GS_Core::ActionIncomingEventBus::Events::DoAction,
AZStd::string("open_door")
);
Listening for Action Completion
#include <GS_Core/GS_CoreBus.h>
class MyActionListener
: public AZ::Component
, protected GS_Core::ActionOutgoingEventBus::Handler
{
protected:
void Activate() override
{
// Listen for action completions on a specific entity
GS_Core::ActionOutgoingEventBus::Handler::BusConnect(m_targetEntityId);
}
void Deactivate() override
{
GS_Core::ActionOutgoingEventBus::Handler::BusDisconnect();
}
void OnActionComplete() override
{
// An action on the target entity has completed
// React accordingly (advance dialogue, open next door, etc.)
}
private:
AZ::EntityId m_targetEntityId;
};
Extending the Action Class
Create a custom action whenever you need a reusable, triggerable behavior that can be attached to any entity.
#pragma once
#include <Source/ActionSystem/GS_ActionComponent.h>
namespace MyProject
{
class PlayEffect_GSActionComponent
: public GS_Core::GS_ActionComponent
{
public:
AZ_COMPONENT_DECL(PlayEffect_GSActionComponent);
static void Reflect(AZ::ReflectContext* context);
protected:
// Action overrides
void ProcessAction() override;
void CompleteAction() override;
private:
AZStd::string m_effectName;
float m_duration = 1.0f;
};
}
Implementation (.cpp)
#include "PlayEffect_GSActionComponent.h"
#include <AzCore/Serialization/SerializeContext.h>
namespace MyProject
{
AZ_COMPONENT_IMPL(PlayEffect_GSActionComponent, "PlayEffect_GSActionComponent", "{YOUR-UUID-HERE}",
GS_Core::GS_ActionComponent);
void PlayEffect_GSActionComponent::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<PlayEffect_GSActionComponent, GS_Core::GS_ActionComponent>()
->Version(0)
->Field("EffectName", &PlayEffect_GSActionComponent::m_effectName)
->Field("Duration", &PlayEffect_GSActionComponent::m_duration);
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
{
// Pattern: Incoming Channel → Feature Properties → Outgoing Channel
editContext->Class<PlayEffect_GSActionComponent>(
"Play Effect Action", "Triggers a named particle effect")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::Category, "MyProject/Actions")
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game"))
->DataElement(AZ::Edit::UIHandlers::Default,
&PlayEffect_GSActionComponent::m_effectName, "Effect Name",
"Name of the particle effect to trigger")
->DataElement(AZ::Edit::UIHandlers::Default,
&PlayEffect_GSActionComponent::m_duration, "Duration",
"How long the effect plays (seconds)");
}
}
}
void PlayEffect_GSActionComponent::ProcessAction()
{
// Your action logic — trigger the particle effect
AZ_TracePrintf("Action", "Playing effect: %s for %.1f seconds",
m_effectName.c_str(), m_duration);
// ... spawn particle effect, start timer, etc. ...
// IMPORTANT: Call CompleteAction when done
// If the action is instant, call it here.
// If it takes time (animation, timer), call it when the effect finishes.
CompleteAction();
}
void PlayEffect_GSActionComponent::CompleteAction()
{
// Custom completion logic (if any)
// ...
// IMPORTANT: Call base to handle broadcast and chaining
GS_ActionComponent::CompleteAction();
}
}
Module Registration
m_descriptors.insert(m_descriptors.end(), {
MyProject::PlayEffect_GSActionComponent::CreateDescriptor(),
});
Reflection Pattern
When reflecting custom action properties in the Edit Context, follow this organization pattern so all actions have a consistent inspector layout:
- Incoming Channel — The
channel property (inherited, reflected by base class) - Feature Properties — Your action-specific properties (effect name, duration, etc.)
- Outgoing Channel — The
broadcastOnComplete and onCompleteChannelChain properties (inherited, reflected by base class)
See Also
1.1 - Core Actions
Pre-built actions included in GS_Core — ready-to-use triggerable behaviors for common game functionality.
Overview
GS_Core includes pre-built Action components for common behaviors. Attach them to any entity, set a channel, and fire them from any system without writing code.
All built-in actions inherit from GS_ActionComponent and follow the same channel-matching, completion, and chaining patterns.
Toggle Mouse Cursor
Toggles the operating system mouse cursor on or off.
When to Use
Use this action when transitioning between gameplay (cursor hidden) and menus (cursor visible). Common triggers include opening an inventory, entering a pause menu, or starting a dialogue sequence.
Inspector Properties
| Property | Type | Default | Description |
|---|
| Channel | AZStd::string | "" | Inherited. The channel this action responds to. |
| Broadcast On Complete | bool | false | Inherited. Broadcasts OnActionComplete when the toggle finishes. |
| On Complete Channel Chain | AZStd::string | "" | Inherited. Fires a follow-up DoAction on completion for chaining. |
Usage Example
#include <GS_Core/GS_CoreBus.h>
// Toggle the cursor when opening the pause menu
GS_Core::ActionIncomingEventBus::Event(
uiEntityId,
&GS_Core::ActionIncomingEventBus::Events::DoAction,
AZStd::string("toggle_cursor")
);
Print Log
Prints a configurable message to the console log. Useful for debugging action chains, verifying event flow, or logging gameplay milestones.
When to Use
Use this action during development to verify that action channels fire correctly, test chaining sequences, or log gameplay events without writing custom components.
Inspector Properties
| Property | Type | Default | Description |
|---|
| Channel | AZStd::string | "" | Inherited. The channel this action responds to. |
| Message | AZStd::string | "" | The message to print to the console log. |
| Broadcast On Complete | bool | false | Inherited. Broadcasts OnActionComplete when the print finishes. |
| On Complete Channel Chain | AZStd::string | "" | Inherited. Fires a follow-up DoAction on completion for chaining. |
Usage Example
#include <GS_Core/GS_CoreBus.h>
// Trigger a debug log message
GS_Core::ActionIncomingEventBus::Event(
debugEntityId,
&GS_Core::ActionIncomingEventBus::Events::DoAction,
AZStd::string("debug")
);
// Console output: whatever message was configured on the PrintLog action
Creating Your Own Action
Need custom behavior? See the Extending the Action Class guide for a complete walkthrough with header, implementation, Reflect pattern, and module registration.
See Also
- Action — Base class documentation and extension guide
- GS_Actions — System overview