Enhanced Input - Detect Gamepad vs Keyboard Input

Hey,

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.

Cheers!

Matt

Any chance you found out how?

I’m also looking how I can do this.

I haven’t found a way with only Enhanced Input, I may use the old soon to be deprecated “Any Key” traditional event until I switch to Common UI.

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.

  1. In the Editor Window go to Edit > Plugins
  2. Search for Common UI and enable it, then restart the editor
  3. 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);
5 Likes

Hi, this worked for me in the Player Controller:

20 Likes

Think nothing is stopping you from adding this old simple check where needed though.
Just make sure to not consume the input.

8 Likes

Or simply Creating a small function in a function library to replace the deprecated IsgamepadKey function.

16 Likes

@BerSeeker 's post, hallelujah, this worked like a charm :slight_smile: thank you!

Thank you kind sir, you saved me just before a build.
May your UE crash at least 33% less.

3 Likes

That’s useful ,thx!

A C++ version of AerolA/Berseeker’s solution.

UInputDeviceSubsystem* InputDeviceSubsystem = GetGameInstance()->GetEngine()->GetEngineSubsystem<UInputDeviceSubsystem>();


//GetPlatformUserID() is part of the Pawn class
if (InputDeviceSubsystem->GetMostRecentlyUsedHardwareDevice(GetPlatformUserId()).PrimaryDeviceType == EHardwareDevicePrimaryType::Gamepad) {
// Code...
}
3 Likes

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…

  1. I use the Query Keys Mapped to Action node for my IA_Interact.
  2. Then I loop through the return array and get the Display Name for each mapped key.
  3. Next, I use Find Substring on each, looking for the substring “Gamepad Face” and checking if the Return Value is greater than -1.
  4. 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.
  5. 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. :sweat_smile:


It does work very well, though.



3 Likes

If your using C++ just make a child class of UEnhancedPlayerInput and add a bool to your player controller and just set it like below.


bool URPEnhancedPlayerInput::InputKey(const FInputKeyParams& Params)
{
	if (PlayerController)
	{
		PlayerController->IsGamepadBeingUsed = Params.IsGamepad();
        }
	return Super::InputKey(Params);
}
4 Likes

Thank you!

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.