Mini-tutorial: The new blueprint support for runtime key-binds / controls remapping / action-mapping

A few months ago Blueprints gained the ability to fully support Unreal’s user-remappable controls (keybinding) system, but almost everything I found on Google still predates this and suggests C or a plugin is the only way. So I thought I’d post a quick overview of these new(ish) tools in case any others were like me under the impression that BP didn’t handle it:

There are two types of controls / bindings in Unreal; Action Mappings (key-bindings), and Axis Mappings (bindings for analog input like mouse position, flight-sticks, controller-thumbsticks, throttles, etc). You can view and edit the existing bindings directly in the editor at Project Settings > Engine > Input > Bindings

(Action/Axis Mappings allow scripts and game controls to be input-agnostic; instead of scripting “when the player pushes the SPACE BAR, make the character jump”, you script “When the player inputs JUMP, make the character jump” and then whichever button the player wishes to assign to JUMP can be used by that player and your script Just Works. If a Mapping (eg JUMP) exists or is created (Project Settings>Engine>Input>Bindings) then when you’re scripting, a rightclick-search for its name (eg “jump”) will reveal an event node of that name to script with.)

The Blueprint nodes for editing the game’s Mappings are:

  • Add Action Mapping

  • Remove Action Mapping

  • Add Axis Mapping

  • Remove Axis Mapping,

    You’ll probably also want to check out;

  • **Get Input Settings **(The nodes above need this)

  • **Get Action Mapping by Name **(Useful for finding bindings the script doesn’t know about)

  • **Get Axis Mapping by Name, **

  • **Make/Break InputActionKeyMapping, **(An Action-mapping structure includes the action NAME, the keypress, plus any modifiers - SHIFT, CTRL, etc)

  • **Make/Break InputAxisKeyMapping, **(An Axis-mapping structure includes the axis NAME, the input/key, plus a float for scale. Eg instead of both a “move-forwards” and a “move-backwards” axis-mapping, you would use just a “move-forwards” axis and map another control to it with the scale set to -1 to get a backwards key)

  • **Make/Break InputChord. **(An InputChord structure is a keypress plus modifiers)

    And in the UMD Editor widget designer; **Palette > Uncategorized > Input Key Selector **
    (This is a menu button that the player uses to do their key remapping. They click it to activate it, then whatever keypress or input they do next, this button will catch it, send that info to the script graph, and display to the player which input/keypress they entered

Below is an example Widget script that is triggered by the player remapping a key in the menu. First the script finds and unbinds all the controls mapped to the JUMP action, then it maps the new player-selected control to the JUMP action:


You can see that the InputKeySelector outputs an InputChord structure, while the AddActionMapping node accepts an InputActionKeyMapping structure, so you use make&break-structure nodes to give the node what it wants. AddAxisMapping likewise has its own input structure - no modifiers and a float for scale.

Here’s what mine looks like to the player; a column of Input Key Selector buttons in the “Options” menu:
keymap3.png

One extra little thing, by default the **InputKeySelector **only accepts keyboard input. If you want to let the player bind mouse-buttons (as seen in the menu above), you’ll want to check the InputKeySelector’sAllow Gamepad Keys” checkbox, seen below:
keymap2.png

I think that’s probably all the info needed to make a nice key-binding menu. Did I miss anything?

(You’ll probably want to do some extra scripting to save the player’s ActionMappings to their savegame file or a config file, and retrieve&set them when the game restarts. I found this part the most time-consuming bit. It’s not different from saving/loading/assigning any other group of arrays of structures, but you’ll also want to update all the **InputKeySelector **buttons in the widget so that they display the new binds that were just loaded. The Set Selected Key node will accept an InputChord and update an InputKeySelector to display that.)

3 Likes

Thanks for this little snippet, It helped me redo our games entire settings system.

Hi @J.Fisher,
thanks for the mini tutorial, I’m struggling a bit to remapping the axis, what you did to get the axis to work?

And again, thanks :slight_smile:

Edit:
Nevermind, found how :slight_smile:

If you want to SAVE YOUR CHANGED MAPPINGS DIRECTLY TO CONFIG without writing an extensive save function, it is very easily done like so:
SaveKeyMappings.png
If you have for example multiple players or users or characters on the same game, then you need a save function,

I haven’t researched how this functions in a packaged game, other than it works. Does it change the defaultinput.ini or does it create an Input.ini under /Saved/? If anyone knows, would be interesting. Some people have reported that reverting to default does NOT work in packaged games.

2 Likes

Thank you for this. I am thinking about thing like this right now. I make Sci-Fi aerial shooter, and I have working joystick/flightstick support, via free plugin (game with anything flying should never be without flightstick support). Maybe anyone made something modular / shareable out of these nodes already? Thank You.

How to manually change display text of InputKeySelector ? There is no function for it.

Does anyone know if there’s a way for multiple simultaneous players to have different controls using this scripting method?

After some brief testing it doesn’t seem like it’s possible (changing bindings for one player changes them in the .ini and therefore for all players.

Hey @MadIBI, I don’t think you can change the text of the Input Key Selector without assigning a key. So if you set the selected key of the Input Key Selector, the text will automatically change.

InputKeySelector.PNG

Does anyone know if it’s possible to call “Start listening to a key” from blueprint? I’d like to call if from blueprint but I can’t find any event for that.

Just wanted to say thanks for this, this is exactly what I needed to know :slight_smile:

Hi, I was wondering how to “clear” an input key selector, basically to remove this binding from the game input settings. I saw that when I right-click on an ***inputKeySelector ***widget it shows “empty” in the widget but there is no event triggered. The ***onKeySelected ***is not triggered, neither is the OnIsSelectingKeyChanged