How do you detect if the player has pressed a Gamepad key or a Keyboard key at run time?
With the old input system, you can get the key directly from the input event and check “Is Gamepad.”
With CommonUI, there is a specific node for this. But with Enhanced Input, I haven’t found an effective method for detecting keyboard/gamepad input at run time.
To my knowledge Enhanced Input has no method of checking input types but as I have done this today, I will post my solution for anyone else searching for a way to access the currently used input method during runtime.
In the Editor Window go to Edit > Plugins
Search for Common UI and enable it, then restart the editor
The ECommonInputType is accessed through Common Input Subsystem via the Player Controller, therefore in Blueprints:
Right click and search for Get Player Controller
Drag from the Return Value pin of Get Player Controller and search for Get CommonInputSubsystem
Drag from the CommonInput Node and search for Get Current Input Type
From the Return Value pin of Get Current Input Type search for Switch for a node Switch on ECommonInputType
You will now have the last used input.
In C++
#include "CommonInputSubsystem.h"
My Enhanced Input Look() function incorporates the solution as
/*
if (const APlayerController* PC = UGameplayStatics::GetPlayerController(this, 0))
{
if (const ULocalPlayer* LocalPlayer = PC->GetLocalPlayer())
{
if (const UCommonInputSubsystem* CommonInputSubsystem = LocalPlayer->GetSubsystem<UCommonInputSubsystem>())
{
if (const ECommonInputType InputType = CommonInputSubsystem->GetCurrentInputType(); InputType == ECommonInputType::Gamepad)
{
AddControllerPitchInput(-LookValue.Y);
}
else
{
AddControllerPitchInput(LookValue.Y);
}
return;
}
}
}
// This is here to add input regardless, should the subsystem checks fail
AddControllerPitchInput(LookValue.Y);
UInputDeviceSubsystem* InputDeviceSubsystem = GetGameInstance()->GetEngine()->GetEngineSubsystem<UInputDeviceSubsystem>();
//GetPlatformUserID() is part of the Pawn class
if (InputDeviceSubsystem->GetMostRecentlyUsedHardwareDevice(GetPlatformUserId()).PrimaryDeviceType == EHardwareDevicePrimaryType::Gamepad) {
// Code...
}
Using the Input Device Subsystem did not detect the change in user input mode at runtime for me. I always output “Keyboard and Mouse” for whatever reason. I had to use the method @Apothecary outlined with the CommonUI plugin to provide the CommonInputSystem. Then I was able to see the value.
My use case is for popup control glyphs. If there’s a better or more standardized way to display dynamic glyphs (keyboard key vs gamepad button), I’d love to know it. Right now I’m binding the Widget Component image sprite to the appropriate image based on the last input type.
This is only vaguely related, but is there a way to also detect which keys are bound to an action in the Input Mapping Context?
For example, if I want to display a simple “Press [E] to open” hint but want to not only take into consideration whether a keyboard ([E]) or gamepad ([X]) is being used but also show the correct button if the player changed their keybinds?
Basically, what I want to check is what keys are mapped to IA_Interact and then decide what glyph to display on screen based on whether it says “Gamepad Face Button Left” (=[X]), “Gamepad Face Button Bottom” =([A]) and so on…
Update:
I found a way to do the above, but it feels quite messy…
I use the Query Keys Mapped to Action node for my IA_Interact.
Then I loop through the return array and get the Display Name for each mapped key.
Next, I use Find Substring on each, looking for the substring “Gamepad Face” and checking if the Return Value is greater than -1.
If it is (greater than -1), I then Get Substring on it, starting at position 20 (to eliminate "Gamepad Face Button "), with a Length of 10 (just to catch everything), and set the result as my GamepadInteractKey variable.
I also check for Key Display Names that return less than 0 for both the substrings Gamepad and Mouse to determine which keyboard key is mapped to IA_Interact, so that I can throw out that prompt correctly and dynamically, too.
It took me way too long to figure out that you need to do all this after a short delay (default of 0.2 works fine), or it won’t work on Begin Play.
Once that’s all done, I “just” needed to assign each face button glyph to its respective mapping… and since I offer multiple glyph sets (Xbox One/Series, Xbox 360, PS4, PS5, Switch Pro and “generic”, I had to do that for each possible set x4… messy af.
Quite simply, by using multiple InputAction’s. For example you can create two actions: IA_Jump IA_JumpController
Inside your InputContextMapping you can assign different keys here. The action events are exposed to Blueprints so I don’t see why you couldn’t implement whatever you’re trying to do. It’s difficult to suggest the most elegant approach when you haven’t given any context in what you’re trying to do.
There is also opportunity to create multiple IMC’s and assign when there’s a hardware change, there’s an OnInputDeviceConnectionChange delegate to detect this. You will want to make sure you check which controller for any logic on this.
In 5.3 we now have UEnhancedInputUserSettings which supersedes the depreciated PlayerMappableInputConfig. You can extend this class to put any logic inside, and assign in project settings.
I would take some time in playing with the above classes as there are better methods than the expensive checks on tick/input change examples given above.