Input Reactors
Categories:
An Input Reactor turns a named input event into gameplay. Input Readers resolve raw device input into named events like "Jump" or "MoveForward"; reactors decide what those events do.
GS_Core owns the mechanism and the extension base. The reactions themselves are authored data, and the concrete reaction types are supplied by whichever gem owns that gameplay domain — GS_Unit ships movement and jump reactors, and your own gem can ship its own.
For usage guides and setup examples, see The Basics: GS_Core.
Contents
- How It Fits Together
- Reactor Profiles
- The Component
- Event Phases
- API Reference
- Writing a Reactor Type
- See Also
How It Fits Together
raw device input
│
▼
Input Reader resolves bindings through the active input profile
│ fires a named event, e.g. "Jump"
▼
Input Reactor classifies the event's phase and dispatches it
│ to every reactor subscribed to that name
▼
reactor types do the gameplay thing
The split matters: the reader knows about devices and bindings, the reactor knows about gameplay, and neither knows about the other’s concerns. Rebinding a key changes nothing about the reaction, and changing a reaction changes nothing about the binding.
Reactor Profiles
InputReactorProfileAsset
A reactor profile is an asset holding AZStd::vector<InputReactorType*> — the set of reactions an entity has.
This is the framework’s polymorphic array shape: the serializer supplies an Add dropdown listing every reactor type reflected anywhere in the project, so a profile can mix reactors from GS_Unit, from another gem, and from your own game.
Because the reaction set is an asset, different entity kinds share or diverge by swapping profiles rather than by rebuilding component stacks.
The Component
GS_InputReactorComponent goes on the entity that should react. It carries one Reactor Profile.
At activation it clones the profile’s reactors so each component owns its own instances, then builds an event-name-to-reactor dispatch map from what each reactor declares it listens to. Cloning is what lets a reactor hold per-entity runtime state — two characters using the same profile do not share it.
It also tracks the current value of every event it has seen, which is what lets it classify phases and answer state queries.
Event Phases
The component classifies each fed event before handing it on, so a reactor is told what kind of input this is rather than having to work it out from value changes.
| Phase | Meaning |
|---|---|
| Pressed | The value went from zero to non-zero on this feed. |
| Held | A repeat feed while the value stays non-zero. |
| Released | The value went from non-zero back to zero. |
| Analog | A continuous update, carrying the raw value. |
Discrete inputs — buttons and keys — produce Pressed, Held and Released. Axis inputs produce Analog with the value.
This is why a jump reactor can be three lines: set the state on Pressed, clear it on Released, and ignore everything else.
API Reference
Request Bus: InputReactorRequestBus
Entity-addressed, single handler. This is how an Input Reader feeds a resolved event to a target entity.
| Method | Parameters | Returns | Description |
|---|---|---|---|
FeedInputEvent | eventName, value | void | Feed a resolved event. The component classifies its phase and dispatches. |
ClearInput | — | void | Clear all tracked event state — used when input should stop mattering, such as entering a menu. |
GetEventState | eventName | float | The current value of a named event. |
Notification Bus: InputReactorNotificationBus
Entity-addressed, multiple handlers. Emitted in parallel with internal reactor dispatch, so ScriptCanvas graphs and other components can react to the same events without being reactor types.
| Event | Parameters | Description |
|---|---|---|
OnInputEvent | eventName, value, phase | An input event fired on this entity. Phase is 0 Pressed, 1 Held, 2 Released, 3 Analog. |
OnInputCleared | — | Input state was cleared. |
This bus is the answer to “I just want a graph to run when the player presses a key” — you do not need to write a reactor type for one-off behaviour.
Writing a Reactor Type
Derive InputReactorType and implement two methods:
| Method | Required | Purpose |
|---|---|---|
GetSubscribedEvents | Yes | The event names this reactor listens to. The component builds its dispatch map from these. |
OnInputEvent | Yes | Called with the owning entity, the event name, its value and its phase. |
OnActivate | No | Connect to downstream systems for this owner. |
OnDeactivate | No | Disconnect. |
Reflect it against the base and it appears in the reactor profile’s Add dropdown. There is no registry to add it to and no discovery step.
Two design habits worth adopting from the shipped reactors:
- Author event names as fields. The shipped reactors expose their event names as editable strings rather than hard-coding them, so one reactor type serves projects with different naming conventions.
- Keep per-owner state on the reactor. Because each component clones its reactors, instance state is safe — the keyboard movement reactor uses this to handle a player releasing one direction key while still holding the opposite one.
See Also
For related systems:
- Input Options — readers and the input pipeline
- Input Profiles — where named events come from
- GS_Unit Input Reactors — the shipped movement and jump reactors
For conceptual overviews and usage guides:
Get GS_Core
GS_Core — Explore this gem on the product page and add it to your project.