Ue Enhanced Input logo

Ue Enhanced Input

Community
kevinpbuckley
ue-enhanced-input

Implement player input with Unreal's Enhanced Input system — UInputAction (data asset, value types Boolean/Axis1D/Axis2D/Axis3D), UInputMappingContext (key-to-action mappings with per-key modifiers and triggers), UEnhancedInputComponent (BindAction with ETriggerEvent), UEnhancedInputLocalPlayerSubsystem (AddMappingContext/RemoveMappingContext), UInputModifier (Negate, SwizzleAxis, DeadZone, Scalar, Smooth), UInputTrigger (Pressed, Released, Hold, Tap, Pulse, ChordedAction), FInputActionValue (Get<bool>(), Get<float>(), Get<FVector2D>(), Get<FVector>()), and PlayerController/Pawn setup. Use when setting up player controls, binding movement/look/jump/interact actions in C++, adding or swapping mapping contexts at runtime (on-foot vs. in-vehicle vs. menu), reading analog values, or migrating from legacy BindAxis/BindAction input.

Overview

Publisherkevinpbuckley
Repositoryunreal-engine-skills
Skill nameue-enhanced-input
Stars
89
Forks
9
Bundled files
3
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 3 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by kevinpbuckley on GitHub. Read the source before you install it.

Installation

Install the Ue Enhanced Input AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/kevinpbuckley/unreal-engine-skills/tree/master/skills/core/ue-enhanced-input
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/kevinpbuckley/unreal-engine-skills.git /tmp/unreal-engine-skills
mkdir -p .claude/skills
cp -r /tmp/unreal-engine-skills/skills/core/ue-enhanced-input .claude/skills/ue-enhanced-input
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Ue Enhanced Input in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Ue Enhanced Input on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Ue Enhanced Input is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Enhanced Input

Enhanced Input is the modern UE input system. It is data-driven: Input Actions define what a player can do, Input Mapping Contexts map physical keys to actions (with optional modifiers and triggers on each mapping), and the Enhanced Input Local Player Subsystem pushes and pops contexts at runtime. Legacy DefaultInput.ini axis/action mappings still compile but are deprecated and should be avoided in new code.

When to use this skill

  • Setting up player controls on a Pawn, Character, or PlayerController.
  • Binding movement, look, jump, interact, or any other player action in C++.
  • Adding, removing, or reprioritizing mapping contexts at runtime (context switching: on-foot, in-vehicle, UI, etc.).
  • Reading analog values from FInputActionValue in an action handler.
  • Replacing legacy BindAxis/BindAction input bindings.

Mental model

Physical key press
   → IMC mapping (modifiers applied first, triggers evaluated)
   → FInputActionValue delivered to handler on matching ETriggerEvent

The system is entirely data-asset-driven. UInputAction and UInputMappingContext are UDataAsset subclasses created in the Content Browser. C++ code holds UPROPERTY pointers to them and uses the subsystem and component to wire them up.

Setup checklist

  1. Verify the Enhanced Input plugin is enabled (on by default in 5.x new projects).
  2. Add "EnhancedInput" to PrivateDependencyModuleNames in your Build.cs.
  3. Set defaults in Project Settings → Engine → Input:
    • Default Player Input Class → EnhancedPlayerInput
    • Default Input Component Class → EnhancedInputComponent
  4. Create a UInputAction asset per action; set the value type (Boolean, Axis1D, Axis2D, Axis3D).
  5. Create a UInputMappingContext asset; add key→action mappings, plus any per-mapping modifiers/triggers.
  6. On possession/spawn: push the context via the subsystem.
  7. In SetupPlayerInputComponent: cast to UEnhancedInputComponent, call BindAction.

Core types

TypeRole
UInputActionAbstract action data asset; carries a ValueType (EInputActionValueType)
UInputMappingContextData asset mapping FKey → UInputAction, with per-mapping UInputModifier[] and UInputTrigger[]
UEnhancedInputComponentInput component subclass; BindAction registers C++ delegates
UEnhancedInputLocalPlayerSubsystemPer-local-player subsystem; AddMappingContext / RemoveMappingContext
FInputActionValueValue delivered to handlers; Get<T>() extracts bool, float, FVector2D, or FVector
ETriggerEventWhen the handler fires: Started, Triggered, Ongoing, Completed, Canceled

Adding a mapping context

Push contexts from a point where the local player exists — typically APlayerController::BeginPlay or APawn::PawnClientRestart:

cpp
// In AMyPlayerController::BeginPlay or APawn::PawnClientRestart
#include "EnhancedInputSubsystems.h"

if (ULocalPlayer* LP = GetLocalPlayer())  // APlayerController has GetLocalPlayer()
{
    auto* Subsys = LP->GetSubsystem<UEnhancedInputLocalPlayerSubsystem>();
    if (Subsys && DefaultMappingContext)
    {
        Subsys->AddMappingContext(DefaultMappingContext, /*Priority*/ 0);
    }
}

Higher-priority values take precedence when two active contexts map the same key to different actions. Remove with Subsys->RemoveMappingContext(IMC). A context can be added/removed any number of times (e.g. entering/leaving a vehicle).

Binding actions in C++

SetupPlayerInputComponent runs on the Pawn after the input component is created. Cast it to UEnhancedInputComponent (safe once the default class is set in Project Settings):

cpp
// AMyCharacter.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "AMyCharacter.generated.h"

class UInputAction;
class UInputMappingContext;
struct FInputActionValue;

UCLASS()
class MYGAME_API AMyCharacter : public ACharacter
{
    GENERATED_BODY()
public:
    virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override;

protected:
    void OnMove(const FInputActionValue& Value);
    void OnLook(const FInputActionValue& Value);

    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
    TObjectPtr<UInputMappingContext> DefaultMappingContext;

    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
    TObjectPtr<UInputAction> MoveAction;   // Axis2D

    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
    TObjectPtr<UInputAction> LookAction;   // Axis2D

    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
    TObjectPtr<UInputAction> JumpAction;   // Boolean
};
cpp
// AMyCharacter.cpp
#include "AMyCharacter.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "InputActionValue.h"

void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
    Super::SetupPlayerInputComponent(PlayerInputComponent);

    // Push mapping context (Pawn path: via controller's local player)
    if (APlayerController* PC = Cast<APlayerController>(GetController()))
    {
        if (ULocalPlayer* LP = PC->GetLocalPlayer())
        {
            auto* Subsys = LP->GetSubsystem<UEnhancedInputLocalPlayerSubsystem>();
            if (Subsys && DefaultMappingContext)
                Subsys->AddMappingContext(DefaultMappingContext, 0);
        }
    }

    auto* EIC = CastChecked<UEnhancedInputComponent>(PlayerInputComponent);

    // Continuous actions use ETriggerEvent::Triggered (fires every tick while held)
    EIC->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AMyCharacter::OnMove);
    EIC->BindAction(LookAction, ETriggerEvent::Triggered, this, &AMyCharacter::OnLook);

    // Jump: Started fires on first press, Completed fires on release
    EIC->BindAction(JumpAction, ETriggerEvent::Started,   this, &ACharacter::Jump);
    EIC->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);
}

void AMyCharacter::OnMove(const FInputActionValue& Value)
{
    const FVector2D Axis = Value.Get<FVector2D>();  // matches IA_Move's Axis2D type
    AddMovementInput(GetActorForwardVector(), Axis.Y);
    AddMovementInput(GetActorRightVector(),   Axis.X);
}

void AMyCharacter::OnLook(const FInputActionValue& Value)
{
    const FVector2D Delta = Value.Get<FVector2D>();
    AddControllerYawInput(Delta.X);
    AddControllerPitchInput(Delta.Y);
}

Key rules:

  • Action UPROPERTY members are assigned in a Blueprint subclass (or in asset defaults). Assign DefaultMappingContext, MoveAction, etc. via EditAnywhere.
  • CastChecked asserts in Debug builds if the cast fails — a fast failure on misconfiguration.
  • The handler signature must exactly match one of the four overloads: no args, const FInputActionValue&, const FInputActionInstance&, or the dynamic four-param form.
  • BindAction returns a FEnhancedInputActionEventBinding& if you need to remove the binding later; store the handle or use RemoveBindingByHandle.

Reading FInputActionValue

cpp
// Match the value type declared on the UInputAction asset:
bool     bPressed = Value.Get<bool>();
float    Analog   = Value.Get<float>();       // Axis1D
FVector2D Axis2D  = Value.Get<FVector2D>();   // Axis2D
FVector   Axis3D  = Value.Get<FVector>();     // Axis3D

Reading the wrong type silently returns zero (e.g. Get<bool>() on an Axis2D action returns false). The correct type is whatever EInputActionValueType the action asset declares.

Trigger events — choosing the right one

Use caseETriggerEvent
Continuous hold (movement, look, accelerate)Triggered
One-shot on press (jump start, fire, interact)Started
One-shot on release (jump release, confirm UI)Completed
Cancel feedback (abort a hold)Canceled
Every frame while held, before threshold metOngoing

Note: Started fires once on the frame the key passes the actuation threshold. Triggered fires every tick while held. Completed fires the frame the key is released (or the trigger condition is fully met and then ends).

WASD as an Axis2D — modifier pattern

A single IA_Move (Axis2D) action can be driven by four keyboard keys using per-mapping modifiers in the IMC:

KeyModifiers on the mapping
WSwizzle Input Axis Values (YXZ) — moves X→Y so W contributes +Y
SSwizzle (YXZ) + Negate — contributes −Y
ANegate — contributes −X
D(none) — contributes +X (default)

At runtime, Enhanced Input accumulates all active mappings for an action per frame (default TakeHighestAbsoluteValue; Cumulative is the alternative, set on the UInputAction asset).

Gotchas

  • Missing "EnhancedInput" in Build.cs → unresolved symbols for all Enhanced Input classes.
  • Default input classes not set → CastChecked<UEnhancedInputComponent> crashes on start; Cast returns null and nothing fires.
  • Mapping context not added → actions never fire; the subsystem must have the IMC before any key can reach an action.
  • Adding context before local player exists → GetLocalPlayer() returns null; always add from PawnClientRestart/BeginPlay (after possession), not the constructor.
  • Value type mismatch → Get<FVector2D>() on a Boolean action yields (0, 0); align the handler type with the action asset's ValueType.
  • Legacy bind calls on UEnhancedInputComponent → BindAxis/BindAction(FName, ...) are deleted (compile error) unless ENHANCED_INPUT_ALLOW_LEGACY_BINDING=1 in Build.cs.
  • Action fires on context add when key is held → default FModifyContextOptions sets bIgnoreAllPressedKeysUntilRelease = true; the key must be released and re-pressed. Set bIgnoreAllPressedKeysUntilRelease = false to override.
  • Priority conflicts — add 0 for most contexts; reserve higher values for overlay contexts (e.g. UI) that must win over gameplay.

Legacy input (you will still encounter it)

Older projects use DefaultInput.ini axis/action mappings and BindAxis/BindAction(FName, ...) on UInputComponent. These still compile in 5.8 but cannot coexist cleanly with UEnhancedInputComponent (legacy binds are explicitly deleted on the enhanced component by default). Migrate by replacing axis/action map entries with UInputAction + UInputMappingContext assets, and replacing BindAxis/BindAction(FName, ...) calls with UEnhancedInputComponent::BindAction.

Version notes

  • Enhanced Input shipped in UE 4.27 as a plugin and became the default system in UE 5.1. In UE 5.7 the Mappings property on UInputMappingContext is deprecated (marked UE_DEPRECATED(5.7)) in favour of the new DefaultKeyMappings struct; use the editor asset instead of editing the Mappings array in C++.
  • FModifyContextOptions (the options struct for AddMappingContext) and input mode filtering via FGameplayTagContainer are 5.3+ additions.

References & source material

Engine source (UE 5.8, plugin path prefix: Engine/Plugins/EnhancedInput/Source/EnhancedInput/Public/):

  • InputAction.h — UInputAction:55 (UDataAsset subclass), EInputActionValueType (InputActionValue.h:10, Boolean/Axis1D/Axis2D/Axis3D), EInputActionAccumulationBehavior:24, FInputActionInstance:207 (GetValue():259, GetTriggerEvent():256).
  • InputActionValue.h — FInputActionValue:23; Get<bool>():205, Get<float>():212, Get<FVector2D>():218, Get<FVector>():224; EInputActionValueType reused here.
  • InputMappingContext.h — UInputMappingContext:87 (UDataAsset subclass); DefaultKeyMappings:101 (5.7 replacement for deprecated Mappings).
  • EnhancedInputComponent.h — UEnhancedInputComponent:373; BindAction template macro DEFINE_BIND_ACTION:480 (four signature overloads); BindActionValue:553; RemoveBinding:475; BindActionInstanceLambda:539.
  • EnhancedInputSubsystems.h — UEnhancedInputLocalPlayerSubsystem:21 (ULocalPlayerSubsystem + IEnhancedInputSubsystemInterface); AddMappingContext:37; RemoveMappingContext:38.
  • EnhancedInputSubsystemInterface.h — IEnhancedInputSubsystemInterface:103; FModifyContextOptions:47 (bIgnoreAllPressedKeysUntilRelease, bForceImmediately, bNotifyUserSettings); HasMappingContext:368; ClearAllMappings:256.
  • InputTriggers.h — ETriggerEvent:34 (None/Triggered/Started/Ongoing/ Canceled/Completed); UInputTrigger:113 (ActuationThreshold:130); concrete triggers: UInputTriggerPressed:279, UInputTriggerReleased:298, UInputTriggerHold:318 (HoldTimeThreshold:334), UInputTriggerTap:365, UInputTriggerPulse:457, UInputTriggerChordAction:494.
  • InputModifiers.h — UInputModifier:16 (ModifyRaw_Implementation); concrete modifiers: UInputModifierDeadZone:170, UInputModifierNegate:253, UInputModifierSwizzleAxis:412 (EInputAxisSwizzle::YXZ), UInputModifierScalar:213, UInputModifierSmooth:275, UInputModifierResponseCurveExponential:306.
  • EnhancedActionKeyMapping.h — FEnhancedActionKeyMapping:37 (Action, Key, Modifiers[], Triggers[]).
  • EnhancedInputDeveloperSettings.h — UEnhancedInputDeveloperSettings:43 (DefaultMappingContexts, bEnableInputModeFiltering, DefaultInputMode).

Official docs (UE 5.8):

Deep-dive references in this skill:

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Ue Enhanced Input AI skill do?

Implement player input with Unreal's Enhanced Input system — UInputAction (data asset, value types Boolean/Axis1D/Axis2D/Axis3D), UInputMappingContext (key-to-action mappings with per-key modifiers and triggers), UEnhancedInputComponent (BindAction with ETriggerEvent), UEnhancedInputLocalPlayerSubsystem (AddMappingContext/RemoveMappingContext), UInputModifier (Negate, SwizzleAxis, DeadZone, Scalar, Smooth), UInputTrigger (Pressed, Released, Hold, Tap, Pulse, ChordedAction), FInputActionValue (Get<bool>(), Get<float>(), Get<FVector2D>(), Get<FVector>()), and PlayerController/Pawn setup. Use...

Why use Ue Enhanced Input on TypingMind?

Because you install it once and use it with any model. Ue Enhanced Input is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Ue Enhanced Input in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/kevinpbuckley/unreal-engine-skills/tree/master/skills/core/ue-enhanced-input. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Ue Enhanced Input?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Ue Enhanced Input?

As many as you like. As long as a model supports skills, you can use Ue Enhanced Input with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Ue Enhanced Input AI skill free?

It is published on GitHub by kevinpbuckley. Check the repository for licensing terms. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇