Skip to content

Enhanced Input Modifiers: Negate, Swizzle, Scalar, and Dead Zone

At a glance

Lives in: an Input Mapping Context mapping or an Input Action asset - Target: an Input Action Value moving through the Enhanced Input evaluation pipeline - Returns: a reshaped value of the same declared action type - Changes: the value seen by later modifiers and triggers, not the physical device value - Can appear to fail by: using the wrong action value type, placing a device-specific modifier on the shared action, ordering modifiers incorrectly, stacking duplicates, or tuning a dead zone without observing raw and final values - Official docs: Enhanced Input, UInputModifier, and UInputModifierDeadZone

The one-minute version

  • Input Modifiers reshape values before Input Triggers decide whether an action actuates. They do not fire gameplay events themselves.
  • A mapping's modifiers run in list order on that physical key or axis. Those mapping modifiers run before modifiers defined on the Input Action asset.
  • Negate flips selected axis signs. Swizzle Input Axis Values reorders components. Together they turn four positive 1D keyboard keys into one signed Axis2D movement action.
  • Scalar multiplies each used axis. It is useful for static sensitivity or direction scaling, but it does nothing useful to a Boolean action.
  • Dead Zone discards small analog noise and remaps or clamps the remaining range. Use a radial mode for a 2D stick when preserving direction matters; use Axial only when independent axis filtering is intentional.
  • Put device- or key-specific shaping on the Mapping Context entry. Put only behavior that should affect every mapping on the Input Action asset.
  • Duplicate modifiers compose. Two Negates can cancel; two Scalars multiply; two Dead Zones distort the range twice.
  • For live per-player sensitivity or inversion, prefer a custom modifier that reads that local player's settings. Do not mutate a shared Input Action data asset at runtime and expect isolated player state.

Where modifiers run

A useful simplified pipeline is:

flowchart LR
    Raw[Raw key or device value] --> MapMods[Mapping modifiers in list order]
    MapMods --> MapTriggers[Mapping trigger qualifiers]
    MapTriggers --> Combine[Combine mappings for the action]
    Combine --> ActionMods[Input Action modifiers in list order]
    ActionMods --> ActionTriggers[Input Action trigger qualifiers]
    ActionTriggers --> Event[Started / Triggered / etc.]

The output of each modifier becomes the input of the next one. Mapping trigger qualifiers inspect that mapping's modified value. Values from mappings that feed the action are combined, then Input Action modifiers reshape the final action value before action-level trigger qualifiers inspect it. Enhanced Input combines the mapping and action trigger results into the action's event state.

A modifier on an individual key mapping is applied before modifiers on the Input Action asset; the two lists combine rather than one replacing the other.

That order has practical consequences:

raw stick magnitude = 0.08
-> Dead Zone removes it to 0
-> trigger sees 0 and stays inactive

raw key value = +1 on X
-> Negate changes it to -1 on X
-> Swizzle YXZ moves it to -1 on Y
-> IA_Move receives (0, -1)

Modifiers do not change the operating system's device reading, remap a key, activate a Mapping Context, bind an Input Action event, or move a pawn. They only transform the value flowing through this action evaluation.

Mapping modifier or action modifier?

Use the narrowest owner that matches the rule.

Location Use it when Example
Mapping Context entry The transformation belongs to this physical key, axis, device, or control scheme. Swizzle W onto Y, negate S, dead-zone a gamepad stick, invert one device axis.
Input Action asset Every mapping that feeds the action should receive the transformation after its values are combined. A universal final response curve or project-wide normalization rule.

For a reusable IA_Move action:

IMC_KeyboardMouse:
    W/A/S/D -> IA_Move with per-key Negate/Swizzle

IMC_Gamepad:
    Gamepad Left Stick 2D -> IA_Move with Dead Zone

IA_Move asset:
    Value Type = Axis2D
    no keyboard-specific modifiers

Putting Swizzle on IA_Move itself is the tempting quick path. The concrete cost is that a correctly oriented gamepad stick is also swizzled. Keep hardware interpretation in the mapping and keep the action semantic: "2D movement intent," regardless of which device produced it.

Negate

Negate multiplies selected components by -1:

(+1, 0) with Negate X -> (-1, 0)
(0, +0.7) with Negate Y -> (0, -0.7)

Choose X, Y, and Z independently in the modifier settings. Common uses:

  • turn a positive A key value into negative X;
  • turn a positive S key value into negative Y before or after moving it onto Y;
  • invert a look axis;
  • reverse a signed throttle or zoom axis.

Negate is not subtraction from 1. Neutral 0 stays 0, positive values become negative, and negative values become positive.

On Boolean actions, "negative true" is not a meaningful Boolean state. Use Negate for signed axis values, and use triggers or gameplay logic when a button's meaning needs to change.

Swizzle Input Axis Values

Swizzle Input Axis Values reorders components. A one-dimensional key value arrives in X by default. Swizzling YXZ moves that X value into Y:

before: (1, 0, 0)
YXZ:    (0, 1, 0)

This does not rotate the value in world space. It only changes which component carries which input number. Actor forward/right vectors are chosen later in the movement graph.

Current EInputAxisSwizzle choices are component orderings such as YXZ. For one-dimensional input moving from X to Y, Epic's directional-input guide allows YXZ or ZXY; both put the original X component in the output Y slot when the unused components are zero. YXZ states the usual X/Y swap most directly.

The standard WASD recipe

Create IA_Move as Axis2D. Add four mappings in the keyboard Mapping Context:

Key Desired action value Mapping modifiers, in order
W (0, +1) Swizzle Input Axis Values: YXZ
A (-1, 0) Negate X
S (0, -1) Negate X, then Swizzle Input Axis Values: YXZ
D (+1, 0) None

Why this works:

every keyboard key begins as a 1D value in X:
    released = 0
    pressed  = +1

W: +X -> swizzle -> +Y
A: +X -> negate  -> -X
S: +X -> negate  -> -X -> swizzle -> -Y
D: +X -> unchanged -> +X

The mappings combine into one Axis2D action value. Pressing W and D together can therefore produce (1, 1). Character Movement normally constrains its accumulated input, but custom movement code should decide whether to preserve, clamp, or normalize diagonal magnitude. See Vector Length and Normalize.

If W moves right, or A moves forward, debug the mapping modifiers before rewriting the movement graph. Print the IA_Move Vector2D directly. It should already use X for right/left and Y for forward/back before actor directions are applied.

Scalar

Scalar multiplies the value per axis by an FVector setting:

input  = (0.5, -0.25)
scalar = (2.0, 0.5)
output = (1.0, -0.125)

Useful cases include:

  • static mouse or stick sensitivity;
  • making horizontal and vertical look speeds differ;
  • reducing one mapping's contribution;
  • multiplying an axis by -1 when a fixed scalar and inversion naturally belong together.

Scalar changes the value that triggers inspect. A Scalar above 1 can make an actuation threshold easier to reach; one below 1 can make it harder. Likewise, scaling movement input and changing Character max speed are not the same operation. One changes player intent before movement; the other changes the movement system's speed limit.

Scalar has no useful effect on a Boolean action because the Boolean contract can only represent false or true. Use Axis1D when analog strength matters.

Do not confuse Scalar with Scale By Delta Time. Scalar uses a fixed factor. Scale By Delta Time multiplies by the current frame's delta and is appropriate only when the downstream contract actually needs a per-frame amount. Most Character movement and look APIs already define their own delta-time behavior; adding another delta factor can make the result frame-rate dependent in the wrong direction.

Dead Zone

Analog sticks and triggers often report small nonzero values near their rest position. A Dead Zone modifier creates a neutral region and remaps the usable range.

Its two thresholds have distinct jobs:

Setting Meaning
Lower Threshold Values below this actuation level are ignored as zero.
Upper Threshold Values at or above this level are clamped to full strength.

Between the thresholds, the ordinary dead-zone behavior remaps the usable range from 0 to 1. That preserves access to full output even though part of the physical range was discarded.

Lower Threshold = 0.20
Upper Threshold = 0.95

small rest noise       -> 0
intentional middle tilt -> remapped middle value
near-full tilt          -> 1

The exact output depends on the dead-zone type and input direction. Tune from observed device values rather than copying one number across every controller.

Axial, Smoothed Radial, or Unscaled Radial?

Current Enhanced Input exposes three dead-zone modes:

Type Behavior Best fit
Axial Applies dead-zone logic to each axis independently. Separate 1D axes, triggers, sliders, or designs that intentionally want axis-by-axis filtering.
Smoothed Radial Evaluates the axes together and applies the normal radial smoothing/remapping. A 2D movement or look stick where direction should remain coherent around center.
Unscaled Radial Evaluates all axes together without the smoothing applied by the normal radial mode. A design that needs a collective radial cutoff but does not want that smooth radial rescaling.

An Axial dead zone on a 2D stick can change direction near the threshold:

raw stick = (0.18, 0.30)
axial lower threshold = 0.20
-> X may become 0 while Y remains active
-> output points straight up instead of preserving the original angle

A radial mode reasons about the stick vector together, which is normally the better starting point for movement and camera sticks. Axial is not wrong; it answers a different question.

Do not add a large dead zone to hide every drift report. A large threshold throws away deliberate fine control. Establish a tolerable neutral floor, test several physical devices, and expose a player setting when the product needs broader hardware support.

Dead zone and response curves

A dead zone decides what counts as neutral and how the usable range begins. A response curve decides how strongly output grows through that usable range. They solve different problems.

raw stick
-> Dead Zone
-> Response Curve - Exponential or Response Curve - User Defined
-> Scalar sensitivity
-> trigger

That is a common order, not a universal law:

  • Dead Zone first removes rest noise before shaping it.
  • An exponential response curve can give finer control near center or a more aggressive response, depending on its per-axis exponent.
  • A user-defined response curve gives authored per-axis control.
  • Scalar then applies an overall fixed sensitivity.

Because each result feeds the next modifier, changing order changes the function. Scalar before Dead Zone changes which raw values cross the dead-zone threshold. A response curve before Dead Zone changes how much of the original physical range gets discarded. Choose the order deliberately and record it in the Mapping Context.

Keep the first tuning pass simple. Dead Zone plus one response curve plus one sensitivity scalar is inspectable. A long modifier stack can produce the same feel, but it is harder to explain, test, and expose as settings.

Duplicate modifiers

Modifiers do not replace an earlier modifier of the same class. They run again:

Stack Result
Negate X, Negate X The two sign flips cancel.
Scalar 0.5, Scalar 0.5 Final factor is 0.25.
Swizzle X/Y, Swizzle X/Y Components return to their original places.
Dead Zone, Dead Zone The already remapped value is filtered/remapped again.
Mapping Scalar, Action Scalar Both apply; the factors compose.

When a value seems inverted, too weak, or unexpectedly zero, inspect both the mapping entry and the Input Action asset. A modifier hidden on the shared action is easy to miss while looking only at the Mapping Context.

Modifiers and triggers

Triggers receive modified values. That means value shaping can alter event state, not only the number printed by the event:

  • a Dead Zone can hold a noisy stick at zero so the action never Starts;
  • a Scalar can move a value above or below a Down trigger's actuation threshold;
  • a Negate preserves magnitude, so a magnitude-based trigger normally still actuates;
  • a Swizzle preserves the same components in a different order, but a custom trigger that inspects a particular axis can behave differently.

Debug the final action value and trigger state together. Seeing a raw device value does not prove the post-modifier value satisfies the trigger.

Runtime player settings

Static modifier settings stored in an Input Mapping Context or Input Action asset are good defaults. They are data-asset configuration, not an isolated runtime settings object for each player.

For per-player inversion, sensitivity, or dead-zone preferences, use an owner that can vary per local player:

  1. Store the preference in a local-player/user settings object.
  2. Implement a custom UInputModifier that reads the owning UEnhancedPlayerInput and its local player's setting during ModifyRaw.
  3. Return the unchanged value if the expected local player/settings object is unavailable.
  4. Test two local players with different settings.

Epic's Enhanced Input guide uses this pattern for Lyra's per-player aim inversion. It avoids changing one shared asset and accidentally changing all players or all mappings that reference it.

For runtime rebinding, use Enhanced Input's player-mappable/user-settings path. Rebinding a key and reshaping the resulting axis are related settings UI work, but they are not the same operation.

A repeatable tuning pass

For a drifting movement stick:

1. Verify IA_Move is Axis2D.
2. Observe the raw/resting stick value on more than one controller.
3. Add one radial Dead Zone to the gamepad mapping.
4. Set Lower Threshold just above acceptable rest noise.
5. Verify slow deliberate tilt still produces controllable output.
6. Verify diagonals preserve direction.
7. Add one response curve only if center-to-edge feel still needs shaping.
8. Add sensitivity Scalar only if the consuming gameplay path expects it.
9. Check the final value and trigger state in play.

Do not tune movement solely by looking at pawn speed. Character Movement, acceleration, braking, max speed, and network correction can all change what you see. First prove the action value, then prove how movement consumes it.

When it appears to fail

  1. Wrong Value Type: Axis2D shaping cannot recover a useful second axis from a Digital action contract.
  2. Wrong modifier location: A keyboard-only Swizzle on the action asset also changes gamepad input.
  3. Wrong order: A threshold sees a scaled or curved value you did not intend.
  4. Duplicate modifier: The Mapping Context and Input Action both reshape the value.
  5. Wrong axis selected: Negate Y does nothing to a 1D key whose value is still in X.
  6. Dead zone too high: Intentional small input is clamped to neutral.
  7. Dead zone type mismatch: Axial filtering changes 2D direction near the threshold.
  8. Trigger threshold mismatch: The modified value exists but never reaches the trigger's actuation requirement.
  9. Stale runtime mapping: The local player's control mappings have not been rebuilt after a supported runtime mapping change.
  10. Downstream lookalike: The action value is correct, but Character Movement, camera code, or UI focus is responsible for the visible result.

Use the Input Action event/value guide to verify the typed value at the binding before changing gameplay code.

Lookalikes - which one do I want?

Tool Use when Not the same as
Negate Flip selected signed axes. Swapping which axis contains a value.
Swizzle Input Axis Values Reorder X, Y, and Z components. Rotating an Actor or converting local space to world space.
Scalar Apply a fixed per-axis multiplier. A nonlinear response curve or max movement speed.
Dead Zone Ignore analog rest noise and reshape the usable range. A trigger actuation threshold with timing/state.
Response Curve Shape sensitivity across the input range. Removing a noisy neutral region.
Input Trigger Decide whether the modified value satisfies press, hold, tap, chord, or actuation conditions. Changing the value itself.
Mapping Context priority Decide which active context wins a physical-input collision. Modifier list order inside one mapping.

Going deeper