Building Key Rebinding in UE5: Change the Jump Key and Save It

Created: 2026-07-20Last updated: 2026-09-05

Add a key-rebinding settings screen to a character that jumps with Space. Separates the initial binding from the player's override and builds it step by step: capturing input with Input Key Selector, registering, changing, and saving in User Settings, and displaying the current key.

"Jump would be easier on J than on Space." When a player feels that way, key rebinding lets them change it themselves. Changing a binding is also called rebinding.

The key name changing on the settings screen is not the finish line. Being able to jump with the new key after closing the screen, and keeping that key after relaunching the game, are all part of one feature.

This article uses a settings screen that changes jump from Space to J as its subject. Get one row working, then extend it to your game's controls.

Changing the key from Space to J and jumping with the same practice character

What You'll Learn

  • The relationship between the initial binding and the player's changed binding
  • Why the change target is registered with User Settings
  • Capturing the pressed key, changing the binding, and displaying the current key
  • Saving changes, cancelling, and restoring the default

Sponsored

Layer the player's change on top of the initial binding

In Enhanced Input, an Input Action (IA) is the action "jump" and an Input Mapping Context (IMC) holds the binding "jump on Space".

To that we add Enhanced Input User Settings , the player's settings. The Space the developer chose stays as the default and the J the player chose sits on top as an override. Think of sticky notes for changes layered over the original table.

ResponsibilityWhat it remembers here
IA_PracticeJumpThe action "jump"
IMC_PlayerControlsThe initial binding, Space
User SettingsThis player uses J

The Blueprint that performs the jump still receives IA_PracticeJump. You do not rewire the Jump node whenever the key changes.

Three layers of IA, IMC, and User Settings, with the player's J layered over the initial Space

With that division, "save the player's change" and "restore the default" can also be handled separately from the jump behavior.

Preparation and registering the row to change

We use Enhanced Input User Settings from UE 5.3 onward. This is for people who know Blueprint variables and functions and basic UMG element placement.

We continue with the practice project from the Enhanced Input introduction. Confirm the following.

  • BP_InputPractice runs as the player and jumps with Space
  • IMC_PlayerControls has exactly one Space Bar binding for IA_PracticeJump
  • The InputSubsystem variable holds the player's Enhanced Input Local Player Subsystem
  • BeginPlay enables IMC_PlayerControls and IMC_Common

We handle just the jump slot. J is unused in Enhanced Input Basics, which makes the change easy to spot. If you switched to drive mode, return to walking first.

1. Enable User Settings

Stop Play, open Enhanced Input from "Edit" → "Project Settings", and turn on Enable User Settings . Save the change, save any open assets, and restart the editor.

User Settings is the entry point that holds and saves per-player changes. Where Enhanced Input Basics' InputSubsystem managed "the control table in use", this handles "the settings this player chose".

2. Name the jump row

Open IMC_PlayerControls and expand IA_PracticeJump's Space Bar row.

  1. Set Setting Behavior to Override Settings
  2. Choose "Player Mappable Key Settings" from the picker and expand its fields
  3. Set Name to JumpKey and Display Name to Jump

Override Settings means "use the settings prepared on this key row". Player Mappable means a binding the player can change.

Name is what you search for later to find the change target. It separates the "Jump" shown on screen from the JumpKey the logic looks for. It does not automatically find the IA's asset name, so keep using JumpKey from here.

Setting the logic-side Name and the display-side Display Name on the jump's Space row

Leave the other key rows alone. Save and close.

3. Register this control table with the settings entry point

In BP_InputPractice, create Get User Settings from Get InputSubsystem. Promote the output to a variable named InputUserSettings .

Fetching User Settings from the Subsystem and storing it in a variable

Rebuild BeginPlay's white wire in this order.

  1. Set InputSubsystem
  2. Set InputUserSettings
  3. Check InputUserSettings with Is Valid
  4. From the Is Valid side, Register Input Mapping Context
  5. The existing Add Mapping Context adding IMC_PlayerControls
  6. The existing Add Mapping Context adding IMC_Common

Register's Target is Get InputUserSettings and the IMC is IMC_PlayerControls. Add's Target is the same Get InputSubsystem as in Enhanced Input Basics. On the Is Not Valid side, Print String User Settings unavailable and stop there.

Checking User Settings and, when valid, registering the IMC before continuing to the existing Adds

Register handles registering the change target and Add handles enabling the control table . They look similar but do different jobs. Going through Register makes the change target JumpKey available in User Settings.

Compile and Play, confirming no errors and that Space still jumps. The key has not changed yet. The side that accepts changes is now prepared.

Build the key-selection settings screen

Stop Play, create a Widget Blueprint, and name it WBP_KeySettings . If UMG is new to you, the Widget Blueprint introduction covers Designer versus Graph.

In the Designer, place a Vertical Box at the center of a Canvas Panel and stack these elements. Aim for about 400 width so text and buttons fit.

ElementNameDisplay / settings
TextFor the headingJump key
Input Key SelectorJumpKeySelectorThe key-choosing element. Is Variable on
TextStatusTextEmpty at first. Is Variable on
Button + TextCloseButtonClose

Input Key Selector waits for the next key when clicked and displays the chosen key. You get a button and input capture without building them. Changing and saving the game's binding, though, is the job of the logic we wire next.

Configure JumpKeySelector as follows.

  • Allow Gamepad Keys: off
  • Allow Modifier Keys: off
  • Key Selection Text: Press a key
  • No Key Specified Text: Not set
  • Escape Keys: add BackSpace
The four elements in WBP_KeySettings and the JumpKeySelector settings

In this exercise, Backspace cancels while waiting for a change. Esc ends Play in the editor, so we use a different key that is easy to test. This is not a practice binding Backspace to jump.

Create these variables on WBP_KeySettings.

VariableTypePurpose
InputUserSettingsEnhanced Input User Settings Object ReferenceThe party we read and write settings on. Instance Editable and Expose on Spawn on
bRefreshingKeyBoolean, default falseThe marker while logic is fixing the display

Expose on Spawn lets you pass a value when creating the Widget. Later BP_InputPractice passes the InputUserSettings it fetched. After setting the variables, compile and save the Widget.

Open the screen and return to game controls

First make the assembled screen openable from the game. Route input to the UI while rebinding and return it to the character on close.

1. Open with the K key

Create a Digital (Bool) IA_OpenKeySettings in the InputPractice folder. Leave Triggers empty and bind it to K in IMC_Common. The key that opens the settings screen is separate from the jump row we are changing.

In BP_InputPractice, call Create Widget from IA_OpenKeySettings' Started with Class WBP_KeySettings.

  • Owning Player: Get Player Controller (Player Index = 0)
  • Input User Settings: Get InputUserSettings

Owning Player is the player using this screen. The Controller you pass is also used when switching input between the UI and the game.

Promote Create Widget's Return Value to a variable named KeySettingsWidget . Wire white exec in this order.

  1. Create Widget → Set KeySettingsWidget
  2. Add to Viewport (Target is Get KeySettingsWidget)
  3. Set Input Mode UI Only
  4. Set Show Mouse Cursor = true
Creating the Widget from Started, passing Owning Player and Input User Settings separately, and storing it in a variable

Set Input Mode UI Only's Player Controller is Get Player Controller's output and In Widget to Focus is Get KeySettingsWidget. Set Mouse Lock Mode to Do Not Lock and turn Flush Input on in versions that have it. Set Show Mouse Cursor uses the same Controller as Target.

Turn on Is Focusable in WBP_KeySettings' Class Defaults. UI Only routes input to the UI while the settings screen is in use.

Displaying the Widget and setting the input destination and mouse cursor

2. Return control with the close button

In WBP_KeySettings, add CloseButton's On Clicked. Wire white exec to Remove From Parent (Target = self) → Set Input Mode Game OnlySet Show Mouse Cursor = false .

Pass Get Owning Player to Game Only's Player Controller and turn Flush Input on. The cursor's Target is the same Get Owning Player. That returns to game controls without carrying over held key states.

Removing the screen from the close button, returning input to the game, and hiding the cursor

Removing the screen alone leaves the input mode at UI Only. Pair closing the screen with returning input to the game.

Compile and Play, then open the screen with K. At this stage the key field can still read "Not set". If "Close" returns control and Space jumps, entering and leaving the screen works. Next we display the actual key in that field.

Sponsored

Read and display the current key

Writing Space every time the settings screen opens would show Space even to someone who already changed it to J. Display the current key, not the default.

Create the RefreshJumpKey function

Create a function RefreshJumpKey on WBP_KeySettings with no inputs or return values.

First, place Find Mappings in Row from Get InputUserSettings with Mapping Name JumpKey. What comes back is the set of bindings belonging to that name. Create To Array from its output to get it as an array.

Since we have only the one Space slot, check whether the array's Length equals 1 .

Converting JumpKey's bindings to an array and comparing the count against 1

From the function entry, wire Set bRefreshingKey = true, then a Branch with that comparison as Condition.

On the Branch's False side, Set Is Enabled = false on JumpKeySelector and Set Text on StatusText to Check the JumpKey registration . Finish with Set bRefreshingKey = false. We confirm there is one slot before reading array index 0.

Raising the refreshing marker and splitting between having one slot and needing to check the registration

What we read from the binding is Current Key, what the player uses now. Default Key is the initial value from the IMC, so we do not use it here.

An Input Chord bundles a key together with modifiers such as Shift. We handle single keys like J and Space here, but wrap them in that form when passing to the Selector.

Taking Current Key from array index 0 and wrapping it in an Input Chord for display

Handle the True side in this order.

  1. Call Set Is Enabled with JumpKeySelector as Target, set to true
  2. Pass the array Get (Index = 0) to Break Player Key Mapping
  3. Pass Current Key to Make Input Chord 's Key. Shift/Ctrl/Alt/Cmd all false
  4. Call Set Selected Key with JumpKeySelector as Target, passing Make Input Chord's output to In Selected Key
  5. Finish with Set bRefreshingKey = false

Get, Break, and Make pass values. White exec runs from the Branch through Set Is Enabled, Set Selected Key, and Set bRefreshingKey.

Enabling the Selector, showing the current key, and clearing the refreshing marker

bRefreshingKey is the marker preventing repeated processing when the display fix is received again as a key change. We use it in the next section.

Call RefreshJumpKey from Event Construct in the event graph. Now the key display is built from the current settings whenever the screen is constructed. Compile and Play, and confirm the field opened with K changes from "Not set" to Space.

Change to the chosen key and save

Select JumpKeySelector in the Designer and add On Key Selected from Details' Events. That is the event you receive when a key is chosen.

1. Do not start the change while refreshing the display

Wire On Key Selected to a Branch with Get bRefreshingKey as Condition. Leave the True side unconnected and continue from False into the key change.

At On Key Selected's entry, ending while refreshing and continuing everything else into the key change

That separates RefreshJumpKey's display updates from the player's chosen change.

2. Pass the chosen key and the change target

Pass the event's Selected Key to Break Input Chord . We wrapped a value for display earlier; now we unwrap it and take the Key.

Place Map Player Key with Target Get InputUserSettings. In Args is the input bundling which slot changes to which key. Create Make Map Player Key Args from that pin and fill in the following.

FieldSetting
Mapping NameJumpKey
SlotFirst
New KeyBreak Input Chord's Key
Hardware Device IdNone
Profile Id fieldsLeave blank
Create Matching Slot If NeededOff
Defer On Settings Changed BroadcastOff

A Slot is a place prepared for a key on the same action. We change only jump's first, so we use First. This is not logic that adds slots. Device identification and multiple profiles stay at their defaults here.

Breaking Selected Key apart and assembling the change values for JumpKey's First slot

Wire white exec from the previous Branch's False into Map Player Key. Confirm that you pass Break Input Chord's Key rather than Selected Key directly into New Key.

Passing the exec wire, the User Settings Target, and the In Args change contents separately into Map Player Key

3. On success, save and re-read the display

Map Player Key's Failure Reason is the container holding reasons the change failed. Zero entries means there were no failure reasons.

Create Get Num Gameplay Tags in Container from Failure Reason and check whether its Return Value equals 0. The node name is long, but what we check is the number of failure reasons. Wire Map Player Key's white output to a Branch with that comparison as Condition.

Comparing the failure-reason count against 0 and splitting between saving and restoring the display

On True, wire Save Settings → RefreshJumpKey → StatusText's Set Text showing Changed . Save Settings' Target is Get InputUserSettings and Set Text's Target is StatusText.

Saving the successful change, re-reading the current key, and displaying the completion message

On False, do not save; wire RefreshJumpKey → StatusText's Set Text showing Could not change it. Check the mapping name and slot . That returns the key the Selector temporarily chose to the key the settings actually hold.

On a failed change, re-reading the original key display and showing a message to check the reason

Map Player Key changes the running binding and Save Settings stores it for the next launch. Closing the screen and continuing the same session makes a missing save easy to overlook, so we relaunch and check later.

Test display, behavior, and saving in order

Changing the key display, testing the jump in game, and relaunching to confirm the setting saved

Compile and save everything, Play, and click the game window.

  1. Confirm Space jumps, land, and press K
  2. The settings screen shows Space
  3. Click the key field and press and release J. "Changed" and J appear
  4. Press "Close". J jumps and Space no longer does
  5. Reopen with K and J is still shown
  6. Click the key field and cancel with Backspace. Staying at J confirms cancelling works

Next, end Play and start it again. Also close the editor, reopen the project, and confirm both J on the settings screen and jumping with J.

Check both that the display persists and that the key actually works . Saved settings load when User Settings initializes, and the Register at launch prepares the same JumpKey entry.

Sponsored

Add a restore-defaults button

Add a Button to the settings screen named ResetButton with the label "Restore defaults".

Call Reset All Player Keys In Row from On Clicked. Target is Get InputUserSettings and In Args is Make Map Player Key Args. Set Mapping Name to JumpKey and leave the rest at defaults.

Restoring JumpKey's row to its initial binding from ResetButton and continuing to the result check

That node restores the specified action row to its initial binding. Our JumpKey has one slot, so it returns to Space. It is not logic that clears the settings for every action.

Check Failure Reason for 0 entries the same way as before and split with a Branch.

  • True: Save Settings → RefreshJumpKey → StatusText showing Restored defaults
  • False: RefreshJumpKey → StatusText showing Could not restore defaults

Change to J, press this button, and confirm the Space display and jumping with Space. Space after relaunching means the restore was saved too.

The structure of keeping the original table and layering the player's change pays off here. You do not need to remember "what the default was" as a separate string on the screen.

Checks when it does not work

First isolate whether you are stuck at "cannot read settings", "cannot change", "does not reach game input", or "does not save".

SymptomWhere to check
User Settings unavailable appearsWhether you enabled Enable User Settings and restarted, and whether Get User Settings' Target is InputSubsystem
Check the JumpKey registration appearsThe Space row's Override Settings, Name = JumpKey, and that Register ran. Also whether you created extra key rows under JumpKey
Create Widget has no Input User Settings inputWhether the Widget's variable has Instance Editable and Expose on Spawn on, and whether you compiled
Selected Key will not connect to New KeyWhether you extracted just the Key with Break Input Chord
"Could not change it" appearsWhether Mapping Name is JumpKey and Slot is First, and whether you changed before registering
It shows J but does not jumpWhether you are in walk mode, whether "Close" returned Game Only, and whether IA_PracticeJump calls Jump
Reopening shows SpaceWhether RefreshJumpKey uses Current Key rather than Default Key
It reverts after a relaunchWhether Save Settings runs after a successful Map, and whether reset logic runs at launch
The display refreshes repeatedlyWhether bRefreshingKey toggles around Set Selected Key and stops things on the On Key Selected side

To investigate further, stringify Map's or Reset's Failure Reason and send it to Print String and Output Log to trace the reason.

Bonus: thinking about adding more actions

What if the same key is chosen?

We tested with the free key J. Binding W from movement or K from opening the settings to jump would conflict. Calling Map Player Key does not automatically tidy things up for your game.

PolicyHow you show it to the player
Allow duplicatesThe same key serves several actions
Reject duplicatesTell them "that key is used for movement"
Swap themMove the existing action to the previous key

Whether both actions run on the same key also involves IMC priority and input-consuming settings. Comparing against other bindings before changing and rejecting duplicates is the easiest to follow at first. Reserving the settings-open key and the cancel key is another approach.

Keep Slots and devices separate

A Slot is the place for holding, say, "Space and J as two candidates" for jump. First and Second do not inherently mean keyboard and gamepad.

To make gamepad bindings changeable too, decide which action, slot, and device you target and align the displayed row with the target passed to Map. Registering several slots under the same JumpKey also means revisiting the Length = 1 check when reading. The gamepad support article is the next entry point.

Apply Settings and saving are not the same

Enhanced Input User Settings' Apply Settings is for applying your own input settings and announcing updates after applying. By default it broadcasts OnSettingsApplied.

Our key change uses Map Player Key, saving uses Save Settings, and re-reading the screen uses RefreshJumpKey, each with its own role. Do not assume "the new key will not save unless Apply is called".

Setting names matter after release too

A Name like JumpKey ties saved settings to the current action. Changing it casually later can break the correspondence with earlier settings.

As you add actions, organize what each row changes: movement, jump, attack. The flow you built on the first row, "read the current value, choose again, verify the result, and save", is reusable for every row.

Summary

Key rebinding connects a screen that waits for keys with settings that hold the player's binding. Input Key Selector receives the key and you change the JumpKey slot registered with User Settings.

When finishing, do not judge success by the display alone; confirm the jump after closing the screen and the key after relaunching. Once one row works end to end, adding more actions uses the same flow.

Reference: User Settings, Registering a mapping context, Map Player Key, Input Key Selector, What Apply Settings does.

Unreal Engine Notes in this section98