Ue Input System
Use this skill when implementing player input with Unreal Engine's Enhanced Input system. Also use when the user mentions 'Enhanced Input', 'input', 'input action', 'InputAction', 'mapping context', 'InputMappingContext', 'input binding', 'key binding', 'input trigger', 'input modifier', 'gamepad', or 'keyboard'. Covers ETriggerEvent, built-in triggers (Hold, Tap, Pulse, ChordAction, Combo), built-in modifiers (DeadZone, Scalar, Negate, SwizzleAxis), and custom trigger/modifier authoring. See references/input-action-reference.md for the full catalogue. For UI input modes, see ue-ui-umg-slate.
- Skill ID
- quodsoler/unreal-engine-skills/ue-input-system
- Publisher
- quodsoler
- Repository
- unreal-engine-skills
- Installs
- 0
- Files
- 2
- Synced
- Sep 23, 2026
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
quodsoler/unreal-engine-skills/ue-input-systemInstalls these files- SKILL.md
- references/input-action-reference.md
What this skill tells the agent
UE Enhanced Input System
You are an expert in Unreal Engine's Enhanced Input system.
Context Check
Read .agents/ue-project-context.md before proceeding. Confirm:
EnhancedInputplugin is listed as enabled- Target platforms (affects which modifiers are needed per platform)
- Whether CommonUI is in use (it manages input mode switching automatically)
- Whether the project still uses legacy input (migration may be needed)
Information Gathering
Ask the developer: what actions are needed and their value types (Bool/Axis1D/Axis2D/Axis3D), which platforms, any complex input requirements (hold-to-charge, double-tap, combos, chord shortcuts), and whether multiple input modes are required (gameplay vs UI vs vehicle).
Enhanced Input Setup
Plugin and Module
.uproject: add { "Name": "EnhancedInput", "Enabled": true } to Plugins.
Build.cs: add "EnhancedInput" to PublicDependencyModuleNames.
DefaultInput.ini:
[/Script/Engine.InputSettings]
DefaultPlayerInputClass=/Script/EnhancedInput.EnhancedPlayerInput
DefaultInputComponentClass=/Script/EnhancedInput.EnhancedInputComponentUInputAction Asset
UInputAction : UDataAsset. Create one per logical player action. Key properties (from InputAction.h):
EInputActionValueType ValueType = EInputActionValueType::Boolean;
// Boolean | Axis1D (float) | Axis2D (FVector2D) | Axis3D (FVector)
EInputActionAccumulationBehavior AccumulationBehavior
= EInputActionAccumulationBehavior::TakeHighestAbsoluteValue;
// TakeHighestAbsoluteValue — highest magnitude wins across all mappings to this action
// Cumulative — all mapping values sum (W + S cancel each other for WASD)
bool bConsumeInput = true; // blocks lower-priority Enhanced Input mappings to same keys
TArray<TObjectPtr<UInputTrigger>> Triggers; // applied AFTER per-mapping triggers
TArray<TObjectPtr<UInputModifier>> Modifiers; // applied AFTER per-mapping modifiersUInputMappingContext Asset
UInputMappingContext : UDataAsset. Maps physical keys to actions.
DefaultKeyMappings.Mappings—TArray<FEnhancedActionKeyMapping>of key-to-action entriesMappingProfileOverrides— per-profile key overrides for player remapping supportRegistrationTrackingMode:Untracked(default, first Remove wins) orCountRegistrations(IMC stays until Remove called N times, safe when multiple systems share it)
Binding Actions in C++
SetupPlayerInputComponent
// MyCharacter.h — declare assets and handlers
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
TObjectPtr<UInputMappingContext> DefaultMappingContext;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
TObjectPtr<UInputAction> MoveAction;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
TObjectPtr<UInputAction> JumpAction;
void Move(const FInputActionValue& Value);
void StartJump();
void StopJump();// MyCharacter.cpp
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
UEnhancedInputComponent* EIC = Cast<UEnhancedInputComponent>(PlayerInputComponent);
if (!EIC) { return; }
EIC->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AMyCharacter::Move);
EIC->BindAction(JumpAction, ETriggerEvent::Started, this, &AMyCharacter::StartJump);
EIC->BindAction(JumpAction, ETriggerEvent::Completed, this, &AMyCharacter::StopJump);
}
void AMyCharacter::BeginPlay()
{
Super::BeginPlay();
if (APlayerController* PC = Cast<APlayerController>(GetController()))
{
if (auto* Sub = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(
PC->GetLocalPlayer()))
{
Sub->AddMappingContext(DefaultMappingContext, 0); // priority 0 = lowest
}
}
}Callback Signatures
BindAction accepts four delegate signatures:
// No params — press/release without value needed
void AMyCharacter::StartJump() { Jump(); }
// FInputActionValue — for axis values
void AMyCharacter::Move(const FInputActionValue& Value)
{
const FVector2D Input = Value.Get<FVector2D>();
AddMovementInput(GetActorForwardVector(), Input.Y);
AddMovementInput(GetActorRightVector(), Input.X);
}
// FInputActionInstance — when elapsed/triggered time is needed
void AMyCharacter::OnChargeAttack(const FInputActionInstance& Instance)
{
const float HeldFor = Instance.GetElapsedTime(); // Started + Ongoing + Triggered
const float ActiveFor = Instance.GetTriggeredTime(); // Triggered only
}
// Lambda variant
EIC->BindActionValueLambda(InteractAction, ETriggerEvent::Triggered,
[this](const FInputActionValue& Value) { TryInteract(); });Storing and removing a binding:
FEnhancedInputActionEventBinding& B =
EIC->BindAction(DebugAction, ETriggerEvent::Started, this, &AMyCharacter::DebugToggle);
uint32 Handle = B.GetHandle();
// ...
EIC->RemoveBindingByHandle(Handle); // remove one binding
EIC->ClearBindingsForObject(this); // remove all bindings for an objectTrigger Events (ETriggerEvent)
Bitmask enum from InputTriggers.h:
| Event | State Transition | Use for |
|---|---|---|
Started | None -> Ongoing/Triggered | First frame of input; press-once actions |
Triggered | *->Triggered, Triggered->Triggered | Every active frame; continuous movement |
Ongoing | Ongoing->Ongoing | Held but not yet triggered (charge build-up) |
Canceled | Ongoing->None | Released before trigger threshold |
Completed | Triggered->None | Input released after triggering; stop continuous actions |
Note: Completed does not fire if any trigger on the same action reports Ongoing that frame.
Built-in Triggers
Full parameter listings in references/input-action-reference.md.
| Class | Name | Behavior |
|---|---|---|
UInputTriggerDown | Down | Every frame input exceeds threshold (implicit default) |
UInputTriggerPressed | Pressed | Once on first actuation; holding does not repeat |
UInputTriggerReleased | Released | Once when input drops below threshold after actuation |
UInputTriggerHold | Hold | After HoldTimeThreshold s; bIsOneShot=false repeats every frame |
UInputTriggerHoldAndRelease | Hold And Release | On release after holding HoldTimeThreshold s |
UInputTriggerTap | Tap | Released within TapReleaseTimeThreshold s |
UInputTriggerRepeatedTap | Repeated Tap | N taps within RepeatDelay (NumberOfTapsWhichTriggerRepeat=2 for double-tap) |
UInputTriggerPulse | Pulse | Repeatedly at Interval s while held; optional TriggerLimit |
UInputTriggerChordAction | Chorded Action | Only fires while ChordAction is active (Implicit type; auto-blocks solo key) |
UInputTriggerCombo | Combo (Beta) | All ComboActions completed in order within TimeToPressKey windows |
Trigger type rules for multi-trigger evaluation: Explicit (default, at least one must fire), Implicit (all must fire), Blocker (blocks everything if active).
Built-in Modifiers
Applied in array order. Mapping-level modifiers run before action-level modifiers.
| Class | Name | Effect |
|---|---|---|
UInputModifierDeadZone | Dead Zone | Zero input below LowerThreshold; remap to 1 at UpperThreshold. Types: Axial, Radial, UnscaledRadial |
UInputModifierScalar | Scalar | Multiply per axis by FVector Scalar |
UInputModifierScaleByDeltaTime | Scale By Delta Time | Multiply by frame DeltaTime |
UInputModifierNegate | Negate | Invert selected axes (bX, bY, bZ) |
UInputModifierSwizzleAxis | Swizzle Input Axis Values | Reorder axes; YXZ (default) swaps X/Y — maps 1D key onto Y of Axis2D action |
UInputModifierSmooth | Smooth | Rolling average over recent samples |
More from quodsoler
Use this skill in a project
Open any RiverX project, search the Skills panel for quodsoler/unreal-engine-skills/ue-input-system, and install it in one click.
