In this article I’ll explain how to add gamepad and keyboard navigation to UI Widgets in Unreal Engine. To my surprise, gamepad navigation magically works alongside regular mouse navigation, as long as Keyboard Focus is set appropriately on any of our UI elements. We don’t need to add any special logic to our project. All we need to do is add a different “focus style” to buttons that are currently hovered over, then set it back to default when we’re done.
Here are the steps involved:
- create a Widget Blueprint
- add it to the viewport with Keyboard Focus
- query if any button has Keyboard Focus
- highlight where appropriate
Creating and adding the Widget
Let’s create a new Widget Blueprint and call it anything you like. Any UI will do to make this work. I have a bunch of regular buttons on my canvas. Mine is called Scroll Menu and will add it in the Level Blueprint. It could also be added to the Player Controller, and ideally it would be hooked up to a “summoning button”, but for brevity and demonstration’s sake I’ll make mine appear immediately. Here’s how I do that.
The first part of the graph grabs a reference to our Player Controller, creates the widget and adds it to the viewport as usual. We’re also setting the input mode to both Game and UI so that gamepad navigation remains enabled.
The last two nodes are the important ones: with a reference to our widget, we extract any focusable UI element (a button in my case) and Set Keyboard Focus. This needs to happen after a short delay, otherwise it won’t work. If done correctly, you should see a dotted outline while navigating your buttons with the game pad, keyboard or hover with the mouse.
Ideally we’d add this only when the player presses a button, at which point we’ll disable her/his being able to move around with the character at the same time. I’m not showing this logic here, but you’d Set Ignore Look Input to false (and back to true when dismissing the menu). There are other ways to do this too, like lowering the time dilation or setting the Player Controller’s Movement Mode to none. I’m sure we’ll cover this in another article. For now we’re done with the Level Blueprint.
Query Button Focus
Next we’ll open the Widget Graph Editor and add some logic to our buttons. We want to query if our magic Keyboard Focus is currently on a button, and if so, change its background colour to give some visual feedback to the player. Pressing buttons with the controller will already work at this point, but apart from the faint dotted outline, it’s tough to make out what’s actually in focus. Here’s how we alleviate this burden:
This looks more dramatic than it actually is: from the top left, we create a custom event called Focus. This is called continuously every 0.1 seconds (looping box ticked). It could alternatively be hooked in to the Event Tick, but for a UI that might be overkill. There are other ways to do this, like call it once and resetting it after any button press.
The Focus event takes an array of buttons, each of which would have been added from our UI. I seem to have a lot of buttons so my array looks a tad mad. We can use the Add Pin option to create additional inputs on the array. With the For Each Loop, we go through every of our buttons and ask if it has Keyboard Focus. If that’s the case, we set the background colour to green, and if it’s false, we’ll set it to a very light grey.
Should the player switch to another button, the previous highlight is cleared out thanks to the false branch, and the new highlight is set via the true branch.
Removing the dotted line
The initial dotted selection outline is still visible though, and that’s an Unreal Engine default setting. We can disable this under Edit – Project Preferences – User Interface. Set the Render Focus Rule to never and the outline will disappear.
I couldn’t quite believe it was so simple. I’ve seen extremely convoluted solutions addressing this relatively simple predicament. It made me wonder if gamepad navigation was indeed a mad science to be mastered after many years of studying, and I’m glad it’s not the case.
All credit for this method goes to Dean Ashford’s YouTube Video, in which he explains this process in detail. Thanks, Dean!