How to detect whether keyboard/mouse or controller was interacted with last

I’d like to make various UI screens auto-adjust their contents based on whether the keyboard/mouse or the controller was touched last by the player. For example an onscreen button might have a label next to it showing which gamepad button to press to activate it, but as soon as the mouse is moved or keyboard is touched, that label will change to show which keyboard key activates it, and vice versa. Fortnite does this throughout it’s UI screens (for example, to switch an icon from B to ESC) so I know it’s possible.

I know how to use events to tell my screens to adjust themselves, but I can’t find any way to query input to know when to do this. I can see that individual UMG widgets can respond to input events (when the mouse is over them), and that the player controller can bind things to input events (outside of UI), but I can’t see any way of global way checking the following, regardless of what else is going on:

  1. is/was any key on the keyboard pressed
  2. is/was any button on the gamepad pressed
  3. was any controller stick/axis just moved
  4. was the mouse just moved

A solution in C++ or Blueprint would be acceptable.

1 Like

I think what you want to do is: track the input events in the Game Instance (EDIT: this does not work), create an event dispatcher, and call it every time your “last controller used” changes. Then bind the events for everyone who needs to listen. Let me know if this helps.

Input Events can’t be used in Game Instance it seems (My bad). But the Player Controller can handle them: right click in the blueprint and type “input action” this should list you all the events you have set in the Project Settings.
EDIT: You can write C++ functions that handle the tracking itself. But I would definitely recommend calling the C++ functions inside the editor/blueprints, since you probably update the input mappings there.

Thanks. That’s roughly what I was thinking - but I can’t see how to track input events from the Game Instance (or the player controller). Am I missing something?

Thanks again, but I don’t think that this does what I need.

Simplistically, here’s what I want:

if ( any keyboard key was pressed || any mouse button was clicked || the mouse was moved )
dispatch event to tell ui widgets to adjust their labels to reflect keyboard/mouse mode
if ( any gamepad button was pressed || any gamepad axis was moved )
dispatch event to tell ui widgets to adjust their labels to reflect gamepad mode

This needs to happen regardless of whether the player is currently ingame or is currently on a UI screen. If I try to use Player Controller events, they aren’t fired while the player is on a UI screen.

That’s odd. Are you disabling any input when you start displaying UI? (IgnoreMovementInput/DisableInput)? Because if you don’t, all input should still work, as long as the player controller is spawned.

Ah yes, apparently I set the input mode to FInputModeUIOnly when I bring up my UI screens (pause menu, for example). I guess I could stop doing that and find a different way to tell the game to ignore control inputs while the UI is visible, but that feels like an inelegant workaround rather than a good solution. I’ll give it a go though. Thanks.

From looking into the code: the UGameViewportClient handles inputs differently when you set FInputModeUIOnly. So the solution would be to edit the UGameViewportClient to catch the last used controller and pass the information down from there.

Try this in the player controller:

There’s also nodes called was input key just released/pressed.

What I ended up doing was going into the engine code and collecting the information in several functions in SlateApplication.cpp, and then exposing that information from there. It may not be the most elegant solution, but all other potential solutions failed in one scenario or another.

hi guys. i’m having exactly the same problem switching between UI to Game. It sounds like you found a solution with the “UGameViewportClient”. Any idea of how can I do that with BluePrints?

The best path I’ve found is to use Game Input Mode and Game/UI Input Mode along with the “Any Key” event on PlayerController. Note that “Any Key” receives all button press events, whether it be keyboard, mouse, or game controller. Make sure to untick “Consume Input” (click on the “Any Key” event and find the option in the settings for the node). Then just use “Is Gamepad Key” on the Key that comes in on the “Any Key” event to determine if the user has pressed a button on the game pad, or something else.

Best of luck

yeha. great answer. I also ended up with the same solution. Be sure to also check the “Execute while paused” option in the “Any Key” event if you want to be able to recover that information while your game’s Pause Menu is opened

For future generations coming to look for this.

Newer versions of Unreal (~4.27+) have the CommonInput Subsystem which takes care of input events and device changes. You can simply bind an event to the input change like this:


and the delegate will give you the device. You can also get the current input type and many other things.

As a subsystem this is accessible from anywhere without having to add any components and it should work in UI as well as any other code classes.

5 Likes

I can create the first node, have you active some plugin?

I think you need to enable and set up common ui. the docs have a quick step by step guide. it should be just a few clicks.

1 Like

If using common UI, this is the correct answer.

Thank you!

1 Like