How-To: Add Input with a Game Feature

Goal: let a game feature plugin bring its own input - mapping contexts, and the ability actions in a UCrimsonInputConfig - and take it all back when the feature deactivates, without editing your pawn for each feature.

Prerequisites
The GameFeatures and ModularGameplay plugins enabled (CrimsonInput already requires both). A UCrimsonInputConfig and an IMC - see How-To: Create an Input Config. A pawn and a player controller that register themselves with UGameFrameworkComponentManager: the mapping-context action watches APlayerController and the binding action watches APawn. Epic's ModularGameplayActors classes call AddGameFrameworkComponentReceiver for you; anything else calls Add Receiver in BeginPlay (C++: PreInitializeComponents) and removes itself in EndPlay.

1. Apply mapping contexts from the feature

Open your Game Feature Data asset, add Add Input Context Mapping to its Actions array, and fill InputMappings. Each entry is an FCrimsonInputMappingContextAndPriority: the InputMapping (your IMC), a Priority (higher wins over lower), and bRegisterWithSettings, which also registers the IMC with the Enhanced Input user-settings subsystem so its mappings show up in a rebinding screen.

The action applies each context through AddMappingContextWithChordTriggers, so chord triggers are injected exactly as they are in How-To: Add Modifier-Key Chords. It runs for every local player, adding on activation and removing on deactivation. This action needs nothing on your pawn.

Verify
Activate the feature and press a key the IMC maps: the action fires. Deactivate it and the same key does nothing.

2. Bind the feature's ability actions

Add Add Input Binding to the same Actions array and fill InputConfigs with one or more UCrimsonInputConfig assets. On activation the action hands each config to the pawn's ICrimsonInputConfigReceiver, which binds the config's ability actions on top of whatever the pawn bound for itself; on deactivation it hands the same configs back to be unbound.

This action does nothing without a receiver
ICrimsonInputConfigReceiver::FindReceiver(Actor) looks at the pawn first, then the first of its components that implements the interface. Find neither and the configs are simply not bound - step 3 is what makes this action work.

3. Implement the receiver on your pawn

ICrimsonInputConfigReceiver is a C++-only interface (CannotImplementInterfaceInBlueprint): it hands out a raw const UCrimsonInputConfig* and is called from the action while the feature state changes. Implement it on your pawn, or on the component that already owns the pawn's UCrimsonInputComponent bindings - whichever holds the bind handles.

A Blueprint-only project uses Add Input Context Mapping (step 1) for the feature's keys and binds its ability actions on the pawn as usual - Enhanced Input Action event per action, into GAS's Try Activate Abilities By Tag, exactly as How-To: Bind Ability Input shows. Skip steps 3 and 4; the mapping-context action needs neither.

Verify
Activate the feature while playing: a key from the feature's config activates the ability it is tagged for. Deactivate it and the same key no longer does.

4. Announce that input is ready

A feature can activate before a pawn exists, or a pawn can be possessed long after the feature is live. Both actions listen for the extension event UCrimsonInputComponent::NAME_BindInputsNow (the name "BindInputsNow") as well as for a new extension. Send it on both the player controller and the pawn once the input component exists and its own bindings are applied, and every already-active feature re-applies onto them.

Event BeginPlay -> Is Locally Controlled (Branch, True) -> Get Game Instance Subsystem (Class = Game Framework Component Manager) -> Send Extension Event (Receiver = Self, Event Name = BindInputsNow), then a second Send Extension Event off the same manager with Receiver = Get Controller. Send both after your own input setup, not before.

Verify
Activate the feature from the console before you possess a pawn, then possess one: the feature's keys work anyway. Play As Client with two clients and confirm each of them binds its own pawn.

Where this runs

Both actions run wherever the feature is active - dedicated server included - but everything they do is local. AddMappingContext and the ability bindings are resolved through UEnhancedInputLocalPlayerSubsystem, which only exists for a local player, so a dedicated server applies nothing and a client binds only its own pawn. Nothing here is replicated state; what the binding eventually activates goes through GAS and replicates on its own.

See also

  • How-To: Create an Input Config - the asset both actions consume.
  • How-To: Bind Ability Input - what AddAdditionalInputConfig is binding on your behalf.
  • How-To: Add Modifier-Key Chords - the trigger injection the mapping-context action performs for you.
  • API Reference -> Game feature actions - every property on both actions.