Input Reactors

The reactor mechanism — a component driven by a reactor profile asset that dispatches named input events to authored reaction types, with a notification bus for scripts.

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

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.

PhaseMeaning
PressedThe value went from zero to non-zero on this feed.
HeldA repeat feed while the value stays non-zero.
ReleasedThe value went from non-zero back to zero.
AnalogA 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.

MethodParametersReturnsDescription
FeedInputEventeventName, valuevoidFeed a resolved event. The component classifies its phase and dispatches.
ClearInput—voidClear all tracked event state — used when input should stop mattering, such as entering a menu.
GetEventStateeventNamefloatThe 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.

EventParametersDescription
OnInputEventeventName, value, phaseAn 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:

MethodRequiredPurpose
GetSubscribedEventsYesThe event names this reactor listens to. The component builds its dispatch map from these.
OnInputEventYesCalled with the owning entity, the event name, its value and its phase.
OnActivateNoConnect to downstream systems for this owner.
OnDeactivateNoDisconnect.

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:

For conceptual overviews and usage guides:


Get GS_Core

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