If you started UE recently you might have set up a Project Settings → Input → Action Mappings and wondered why the editor warns you it's deprecated. Or you tried to follow an Enhanced Input tutorial and got lost between "Input Actions", "Input Mapping Contexts", "Modifiers" and "Triggers" — four things that all sound like the same thing.
The Enhanced Input System is genuinely better than the old one once you see the mental model. The trick is understanding why four concepts.
The 30-second mental model
Imagine you're describing a control scheme to a designer:
"There's an action called Jump. On gamepad, it's the A button. On keyboard, it's Space. Hold it longer than 0.3 seconds and it counts as a charged jump."
That sentence contains four different things:
- Input Action: "Jump" — the abstract thing you want to do.
- Input Mapping Context: "On gamepad / on keyboard" — which physical key binds to it, in this layer.
- Trigger: "longer than 0.3 seconds" — when the action fires.
- Modifier: not in the sentence, but think: "invert Y axis" — how the raw input is transformed before it becomes the action's value.
The old system mashed these together: one Action Mapping per key with no per-context awareness, hardcoded threshold, no value transformation. Enhanced Input separates them so you can ship different control schemes for different game states without rewriting input code.
Input Action — the verb
An Input Action is the abstract verb: "Jump", "Move", "Interact", "OpenInventory".
It doesn't know which key triggers it. It just has a Value Type: Bool (button), Axis1D (trigger / scroll), Axis2D (stick / WASD-as-direction), Axis3D (rare, 3D-pad).
Create one: Content Browser → right-click → Input → Input Action. Name it IA_Jump, IA_Move, etc.
That's it. No keys, no logic. Just the verb.
Input Mapping Context — the binding layer
An Input Mapping Context (IMC) is a collection of "this key triggers that Input Action". It's the binding layer.
Crucially, you can have multiple Mapping Contexts active at the same time, and they layer with priorities. That's the killer feature.
Example:
IMC_Default(priority 0): Move on WASD, Jump on Space, Interact on E.IMC_Driving(priority 10): Accelerate on W, Brake on S, Steer on A/D.IMC_Menu(priority 100): UI navigation only — blocks everything else.
When the player gets in a car, you push IMC_Driving. When they open a menu, you push IMC_Menu on top. When they close it, you pop it. WASD now does the right thing in each state with zero if (in_menu) { ... } else if (in_car) { ... } spaghetti.
Activating a Mapping Context — the one weird trick
Mapping Contexts don't activate themselves. You have to add them to the local player's Enhanced Input subsystem. The boilerplate:
CB0
Set this up once in your Character (or PlayerController), and your default bindings are live. Push other contexts at runtime — Add Mapping Context for adding, Remove Mapping Context for popping.
Reading the action in your character
In your Character Blueprint, you can now bind to the Input Action directly:
CB1
The event has four execution pins:
- Triggered — fires every frame the action is active (Bool: while button held, Axis: while value non-zero).
- Started — fires once when the action goes from inactive to active.
- Ongoing — fires while the action is "trying" but hasn't reached its trigger threshold yet.
- Completed — fires once when the action ends naturally.
- Canceled — fires when the action ends abnormally (e.g. another context took priority).
The output pin Action Value is the typed value: Bool for Jump, Vector2D for Move, Float for an axis trigger.
For a Move action of type Axis2D, this gives you the WASD vector directly — (1, 0) for D, (-1, 0) for A, etc. No more if (W) ...; else if (S) ...; else if (A) ....
Modifiers — the underrated feature
Modifiers transform the raw input value before the action fires. They live on the binding inside a Mapping Context. Most useful ones:
- Negate: flips the sign. For mapping "S" to "Move backward", you don't write a separate Action — you bind S to
IA_MovewithNegate (Y)modifier. - Swizzle Input Axis Values: rearranges XYZ. Useful when a 1D axis needs to become a 2D vector's X (or Y).
- Dead Zone: ignores tiny stick wiggles around centre. Set this on gamepad bindings.
- Scalar: multiply. For accessibility: a "slow movement" mode multiplies the move vector by 0.5.
- Smooth: applies an exponential smoothing curve. Camera look benefits from a small one.
Set them in the Mapping Context entry, not the Input Action. The same Input Action can have different modifiers per Mapping Context.
Triggers — when the action fires
Triggers are the rules for when an action reports as active.
- Down (default for Bool): active while button held.
- Pressed: fires once on press.
- Released: fires once on release.
- Hold: fires after holding for N seconds.
- Tap: fires if pressed and released within N seconds.
- Pulse: fires at a rate while held (e.g. for auto-fire).
- Chorded Action: fires only if another action is also active (e.g. Shift+W for Sprint).
Stack triggers on a single binding when you need "Tap and Hold do different things on the same key". Two separate triggers in the list → two separate execution paths from the same Input Action event.
Plugin tip
Enhanced Input nails the basics — Action / Context / Trigger / Modifier. What it doesn't ship: input buffers (queue a jump just before landing), gesture recognition (circle, double-tap, swipe), or combo windows for fighting games.
FoxInput layers exactly that on top — buffer, gestures, combos, context-stacking helpers — without replacing Enhanced Input. Optional, but if your game needs any of those, this saves a week.Common pitfalls
- Forgetting to add the Mapping Context. You wire up the IA event in your Character and nothing happens. Check: does
BeginPlayactually callAdd Mapping Context? - Bool action with negative value. A Bool action ignores sign. If you bind S to a Bool IA with Negate, S is treated as "active". Use Axis1D + Negate instead.
- Mapping Context priority confusion. Higher number = higher priority = consumed first. Default contexts at 0, overlays at 10+, menus at 100+.
- Tap and Down on the same key. Down fires every frame while held; Tap fires once on release if quick enough. Stacking them on one binding causes both to fire on a quick tap. Pick one.
- Calling
Add Mapping Contextfrom BeginPlay on the server in a multiplayer game. Input is client-side. Use the Local Player Subsystem from the correct client controller, or you'll wonder why nothing responds for the second player.
The 30-second recap
- Input Action: the verb. No keys, no logic.
- Input Mapping Context: which key → which action, layered by priority.
- Modifier: transforms raw input before the action fires (Negate, Dead Zone, Scalar, ...).
- Trigger: when the action fires (Pressed / Hold / Tap / Pulse / Chorded).
- Activate a Mapping Context via
Get Enhanced Input Local Player Subsystem → Add Mapping Context. - Bind to actions in your Character with
Enhanced Input Action IA_Xevents.
Once you've thought of it as Verb / Bindings / Transform / Timing instead of "uhh, four things that all sound similar", it's much cleaner than the old if input == "W" chain.
Next week: Blueprint or C++? A pragmatic guide. Now that you can move a character around, you'll inevitably hit the question every UE dev hits at some point. Spoiler: the answer isn't "C++ for performance, Blueprint for prototyping" — it's more interesting than that, and the wrong choice early costs months later.
— Marco
Comments
Leave a comment