How-To: Touch Input Widgets

Goal: an on-screen virtual joystick and buttons for mobile that inject values into Enhanced Input - your gameplay code keeps listening to the same UInputActions it uses for gamepad and keyboard.

Prerequisites
Enhanced Input actions your game already binds (e.g. IA_Move as Axis2D, IA_Fire as Digital (bool)). The touch widgets live in your HUD layout.

1. Virtual joystick

Create a widget Blueprint with parent Crimson Joystick (UCrimsonJoystickWidget). Add two Image widgets named exactly JoystickBackground (the static ring) and JoystickForeground (the moving thumb) - both are BindWidget. In Class Defaults set:

PropertyCategoryNotes
AssociatedActionInput (inherited from the simulated-input base)The Axis2D action to inject into, e.g. IA_Move.
StickRangeJoystickMax thumb travel in pixels (default 50); output is normalized from it.
bNegateYAxisJoystickFlip Y if pushing up should mean forward in your mapping.
FallbackBindingKeyInputKey whose injection route is used when the action has no live binding (default Gamepad_Right2D).
Screenshot pendingImages/CrimsonUI/howto-joystick-setup.png
WBP_MoveStick (parent: Crimson Joystick): hierarchy shows JoystickBackground + JoystickForeground Images; Class Defaults show Associated Action = IA_Move, Stick Range = 50.
Verify
PIE with touch emulation (or a device): dragging the stick moves the pawn through your existing IA_Move binding; releasing recenters the thumb and zeroes the input.

2. Touch regions (virtual buttons)

Crimson Touch Region (UCrimsonTouchRegion) injects its AssociatedAction while a finger is inside the widget - an on-screen Fire/Jump button with zero graph logic. Style it however you like; the widget's whole geometry is the hit zone.

3. Custom touch widgets

Subclass Crimson Simulated Input Widget (UCrimsonSimulatedInputWidget) for anything custom (gesture pads, radial sticks). BlueprintCallable helpers: InputKeyValue / InputKeyValue2D (inject a value this frame), FlushSimulatedInput (zero everything - call on touch end), GetSimulatedKey (the key it resolved from the player's mappings), GetEnhancedInputSubsystem. The base also hides itself on non-touch platforms via its CommonVisibilityBorder.

Local-only by design
Injected input goes through UEnhancedInputLocalPlayerSubsystem on the owning client, exactly like a physical device. Nothing here replicates; the server sees the resulting gameplay (movement, ability activation) through the normal channels.

See also

  • How-To: HUD Layout & Escape Menu - where touch widgets live.
  • CrimsonInput wiki - the tag-driven layer those same actions plug into.