UE Input System
Target engine: UE 5.8. APIs below are verified against the 5.8 headers; older forms are listed under "Deprecated — do not use".
Enhanced Input is the engine's only supported input path. It lives in the EnhancedInput plugin (Engine/Plugins/EnhancedInput, enabled by default in 5.8); add "EnhancedInput" to PublicDependencyModuleNames in your Build.cs, plus "InputCore" if you touch FKey/EKeys directly and "GameplayTags" if you use input-mode filtering or the user-settings failure-reason containers. The runtime pieces are UEnhancedPlayerInput, UEnhancedInputComponent, UEnhancedInputLocalPlayerSubsystem, the data assets UInputAction / UInputMappingContext, and UEnhancedInputUserSettings for player rebinding.
Context
Read .agents/ue-project-context.md if it exists (module names, conventions, enabled plugins, GAS/networking setup). Do not stop if it is missing.
Identify the area from the request and the codebase. Ask only when two plausible readings would produce different code.
Full per-class parameter tables live in references/input-action-reference.md [blocked].
Setup
DefaultInput.ini — point the engine's default classes at Enhanced Input:
Enhanced Input project settings live on UEnhancedInputDeveloperSettings (Project Settings → Engine → Enhanced Input), written to DefaultInput.ini under [/Script/EnhancedInput.EnhancedInputDeveloperSettings]. Keys that change C++ behaviour: bEnableUserSettings, UserSettingsClass, DefaultPlayerMappableKeyProfileClass, InputSettingsSaveSlotName, bEnableWorldSubsystem, DefaultWorldInputClass, bEnableInputModeFiltering, DefaultMappingContextInputModeQuery, DefaultInputMode, bEnableDefaultMappingContexts, bSendTriggeredEventsWhenInputIsFlushed.
Input Assets
UInputAction : UDataAsset — one per logical player action. Properties that change C++ behaviour:
UInputMappingContext : UDataAsset — key-to-action bindings, added and removed as a set.
Each FEnhancedActionKeyMapping carries Action, Key, per-mapping Triggers, Modifiers, a SettingBehavior (EPlayerMappableKeySettingBehaviors: InheritSettingsFromAction, OverrideSettings, IgnoreSettings) and an optional PlayerMappableKeySettings override. Reach them with GetPlayerMappableKeySettings() and GetMappingName().
Binding Actions in C++
Handler signatures
UEnhancedInputComponent::BindAction returns FEnhancedInputActionEventBinding& and accepts a member function matching one of three native delegate signatures, or a UFUNCTION by name:
FInputActionInstance exposes GetValue(), GetTriggerEvent(), GetElapsedTime() (Started + Ongoing + Triggered), GetTriggeredTime() (Triggered only), GetLastTriggeredWorldTime(), GetTriggers(), GetModifiers() and GetSourceAction().
Lambdas and pollable values:
Removing bindings:
Trigger Events
ETriggerEvent is a bitmask (ENUM_CLASS_FLAGS) describing the trigger-state transitions seen this tick.
Started always fires before Triggered when both occur on the same tick. Completed does not fire on a tick where any trigger on the action reports Ongoing — split press and release into two actions if you need both reliably.
Built-in Triggers
Per-class properties and defaults: references/input-action-reference.md [blocked].
ETriggerType decides how triggers combine on one action: Explicit (at least one must fire), Implicit (all must fire), Blocker (blocks everything while IsBlocking returns true). ETriggerEventsSupported (None, Instant, Uninterruptible, Ongoing, All) declares which ETriggerEvents a trigger can ever produce.
Built-in Modifiers
Per-mapping modifiers run first, then the action-level Modifiers array; each group runs in array order.
WASD → Axis2D (AccumulationBehavior = Cumulative on the action):
W:Swizzle Input Axis Values (YXZ)→ Y = +1S:Swizzle Input Axis Values (YXZ)+Negate (bY)→ Y = −1D: none → X = +1A:Negate (bX)→ X = −1
Gamepad stick: Dead Zone (Radial, LowerThreshold = 0.2) on each stick mapping.
Mouse look: Scalar(0.4, 0.4, 1.0), then Smooth, then FOV Scaling on the mapping.
Mapping Contexts and Priority
FModifyContextOptions defaults: bIgnoreAllPressedKeysUntilRelease = true, bForceImmediately = false, bNotifyUserSettings = false. The first one already suppresses ghost inputs from keys held across a context switch — do not set it explicitly thinking it is opt-in; set it to false only when you deliberately want a held key to carry into the new context.
bConsumeInput = true on a UInputAction (the default) means a higher-priority context mapping the same physical key blocks every lower-priority binding of that key. Use priority plus bConsumeInput to keep modes apart — a vehicle context consuming Spacebar stops the character's Jump action firing while driving.
RegistrationTrackingMode on the IMC: Untracked (the first RemoveMappingContext wins, whatever the add count) or CountRegistrations (stays applied until removed as many times as it was added — use it when several systems share one IMC).
Each local player owns a separate UEnhancedInputLocalPlayerSubsystem, so split-screen contexts never leak between players. Fetch a specific player's subsystem with ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(LocalPlayer) or ULocalPlayer::GetSubsystemFromController<UEnhancedInputLocalPlayerSubsystem>(PlayerController). Simulate input without a device with InjectInputForAction(Action, RawValue, Modifiers, Triggers) or InjectInputVectorForAction(Action, Value, Modifiers, Triggers).
Input Mode Filtering
Gate whole mapping contexts on a gameplay-tag state instead of adding and removing them. Requires bEnableInputModeFiltering on UEnhancedInputDeveloperSettings.
- The subsystem holds the current mode:
GetInputMode(),SetInputMode(Tags, Options),AppendTagsToInputMode,AddTagToInputMode,RemoveTagsFromInputMode,RemoveTagFromInputMode— all take an optionalFModifyContextOptions. - Each
UInputMappingContextchooses how it is matched viaInputModeFilterOptions:UseProjectDefaultQuery(the project'sDefaultMappingContextInputModeQuery),UseCustomQuery(the IMC's ownInputModeQueryOverride), orDoNotFilter. UEnhancedInputDeveloperSettings::DefaultInputModeseeds the mode on every newUEnhancedPlayerInput.- Contexts whose query fails stay registered but stop producing input, so priorities and registration counts are untouched.
Runtime Key Rebinding
UEnhancedInputUserSettings (UserSettings/EnhancedInputUserSettings.h) is the sanctioned rebinding path. It is a USaveGame, created per subsystem when bEnableUserSettings is on, and saved to the slot named by InputSettingsSaveSlotName.
Register any IMC the settings UI must list — even one never added to the subsystem — with RegisterInputMappingContext(IMC); adding a context with bNotifyUserSettings = true does it for you. Read mappings back with FindMappingsInRow(MappingName) and FindCurrentMappingForSlot(MappingName, Slot), reset with ResetAllPlayerKeysInRow or ResetKeyProfileIdToDefault, and persist with SaveSettings() / AsyncSaveSettings(). Profile identifiers are FString, not FGameplayTag — ProfileIdString, GetProfileIdString(), GetActiveKeyProfileId(), GetKeyProfileWithId(), SetActiveKeyProfile().
An action or mapping is only rebindable if it carries a UPlayerMappableKeySettings (Name, DisplayName, DisplayCategory, Metadata, SupportedKeyProfileIds) — either on the UInputAction or on the FEnhancedActionKeyMapping with SettingBehavior = OverrideSettings. Full API and struct tables: references/input-action-reference.md [blocked].
Input Without a PlayerController
UEnhancedInputWorldSubsystem (Experimental in 5.8) lets actors that will never be possessed receive input delegates. Enable it with bEnableWorldSubsystem in UEnhancedInputDeveloperSettings.
Pair every AddActorInputComponent with RemoveActorInputComponent on EndPlay. The subsystem implements the same IEnhancedInputSubsystemInterface as the local-player one, so AddMappingContext, InjectInputForAction and friends behave identically — but it has no user settings and no local player.
Per-Platform Input Data
UEnhancedInputPlatformSettings (UPlatformSettings, UEnhancedInputPlatformSettings::Get()) holds an InputData array of UEnhancedInputPlatformData subclasses. Each one defines MappingContextRedirects, a TMap swapping one UInputMappingContext for another on that platform; GetContextRedirect(Context) returns the replacement or the original. Use it to substitute a touch or console context without branching in gameplay code. Calling Get() needs DeveloperSettings in Build.cs (it inlines a UPlatformSettingsManager call).
Custom Triggers
Subclass UInputTrigger and override UpdateState_Implementation, returning ETriggerState::None, Ongoing or Triggered.
IsActuated(Value) is Value.GetMagnitudeSq() >= ActuationThreshold * ActuationThreshold. For time-based triggers derive from UInputTriggerTimedBase, which transitions to Ongoing on actuation and gives you HeldDuration plus CalculateHeldDuration(PlayerInput, DeltaTime) and bAffectedByTimeDilation. Override IsBlocking(const ETriggerState State) const for blockers and GetDebugState() const for the debug HUD. If your trigger keeps state across mapping rebuilds, override ReceiveTriggerReinstanced_Implementation(const UInputTrigger* OldTrigger) and call Super.
Custom Modifiers
Subclass UInputModifier and override:
The returned value is converted back to the action's ValueType before further processing, so you may return any shape internally — FInputActionValue(CurrentValue.GetValueType(), Vector) preserves it. Override GetVisualizationColor_Implementation(FInputActionValue SampleValue, FInputActionValue FinalValue) const to control the debug overlay colour. Worked example: references/input-action-reference.md [blocked].
UI Input Mode
Without CommonUI, switch modes on the PlayerController with SetInputMode(FInputModeUIOnly()), SetInputMode(FInputModeGameAndUI()) or SetInputMode(FInputModeGameOnly()).
CommonUI routes input through UCommonActivatableWidget stacks and removes most manual SetInputMode calls. Enhanced Input and Common Input are unified: turn on UCommonInputSettings::bEnableEnhancedInputSupport (Project Settings → Game → Common Input; requires a restart) and CommonUI's click and back actions become UInputAction assets — UCommonUIInputData::EnhancedInputClickAction and EnhancedInputBackAction — instead of data-table rows. Widget stacks, activatable widgets and input configs belong to ue-ui-umg-slate.
Debugging
ShowDebug EnhancedInput prints the applied mapping contexts, each action's value and trigger state, and each trigger's GetDebugState(). ShowDebug WorldSubsystemInput does the same for UEnhancedInputWorldSubsystem; ShowDebug InputSettings dumps the developer settings; LogWorldSubsystemInput at VeryVerbose logs every key the world subsystem processes.
Deprecated — do not use
Common Mistakes
Adding the mapping context in SetupPlayerInputComponent: that call can run before the controller and local player are resolved. Add contexts in BeginPlay, OnPossess/PossessedBy, or a PlayerControllerChanged handler.
Setting bIgnoreAllPressedKeysUntilRelease = true "to be safe": it is already the default on FModifyContextOptions. Only touch it to set false.
Binding Triggered for a button press: Triggered fires every active frame. Use Started for press-once and Completed for release.
Expecting Completed alongside Ongoing: Completed is suppressed on any tick where a trigger reports Ongoing. Split into two actions with their own triggers.
No dead zone on sticks: analog sticks rest at non-zero. Add Dead Zone (Radial) to every stick mapping.
Missing swizzle for WASD: a keyboard key produces a 1D value on X. Without Swizzle Input Axis Values (YXZ) on W and S, forward/back never reaches the Y component of an Axis2D action.
Calling MapKey/UnmapKey for player rebinding: those mutate the IMC asset and are editor/config helpers. Use UEnhancedInputUserSettings::MapPlayerKey instead, and pass bNotifyUserSettings = true when adding contexts you want listed in a rebinding UI.
Replicating trigger events: input is client-local. Replicate the result — movement input, ability activation — never the ETriggerEvent.
Legacy binding on a UEnhancedInputComponent: BindAxis and the FName BindAction overloads are = delete and fail to compile. Migrate them rather than defining ENHANCED_INPUT_ALLOW_LEGACY_BINDING=1.
Related Skills
ue-gameplay-framework—APlayerController, possession,SetupPlayerInputComponentlifecycleue-ui-umg-slate— CommonUI activatable-widget stacks, input configs, cursor and focusue-character-movement— consumingFInputActionValuethroughAddMovementInputue-gameplay-abilities— activating abilities from input,UAbilitySystemComponentinput IDsue-actor-component-architecture—UActorComponent/UInputComponentownership,EnableInput, component-owned input- Also relevant:
ue-cpp-foundations,ue-game-features,ue-gameplay-cameras,ue-mover


