What is the recommended way to detect gamepad events? I’m thinking of the following scenarios:
- Gamepad is connected and gets disconnected
- Gamepad is disconnected and gets connected
Also, battery level would be nice. I’m interested in Windows only.
What is the recommended way to detect gamepad events? I’m thinking of the following scenarios:
Also, battery level would be nice. I’m interested in Windows only.
I’ve looked through the source and can say that events for gamepads connecting/disconnecting do not exist. XInput has an XInputGetBatteryInformation call that isn’t plumbed. There’s also no way to query the number of detected gamepads. There’s quite a lot missing here.
I did find a way to poll whether an Xbox controller is connected, although it may make your eyes bleed with terrible programming practice… (this needs to be implemented in C++)
At the top of your CPP file, add:
#if PLATFORM_WINDOWS
#define private public
#include "Runtime/Core/Public/Windows/WindowsApplication.h"
#include "Runtime/Core/Private/Windows/XInputInterface.h"
#undef private
#endif
Then implement a function to return whether an Xbox gamepads are connected:
bool XboxControllerConnected()
{
#if PLATFORM_WINDOWS
if (FSlateApplication::IsInitialized() && FSlateApplication::Get().GetPlatformApplication().IsValid())
{
TSharedPtr<FWindowsApplication> app = StaticCastSharedPtr<FWindowsApplication>(FSlateApplication::Get().GetPlatformApplication());
if (app.IsValid())
{
TSharedPtr<XInputInterface> x = app->XInput;
if (x.IsValid())
{
for (int i = 0; i < MAX_NUM_XINPUT_CONTROLLERS; i++)
{
if (x->ControllerStates[i].bIsConnected)
return true;
}
}
}
}
#endif
return false;
}
Huge disclaimer here though:
This is not a good/sustainable/safe approach to solving this problem. Use at your own risk, and know that future updates of the engine could easily break this.
Lol, yes my eyes are bleeding, but at least it’s something that works for now.
This solution worked for me, but I opted for the engine change at the link below because it relies less on the dark arts.
Thanks for the update - that’s definitely a better solution if you are willing to compile your own engine
Here is possible solution, only tested on windows so far.
File - New C++ Class
Choose parent class - Blueprint Function Library, hit next
Give it a name (for example GamepadDetection)
GamepadDetection.h
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "GamepadDetection.generated.h"
/**
*
*/
UCLASS()
class PROJECTNAME_API UGamepadDetection : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
/* Check if gamepad is connected at Runtime. */
UFUNCTION(BlueprintCallable, meta = (DisplayName = "GamepadConnected"), Category = "System Information")
static bool IsGamePadConnected();
};
GamepadDetection.cpp
#include "GamepadDetection.h"
#include "SlateBasics.h"
bool UGamepadDetection::IsGamePadConnected()
{
auto genericApplication = FSlateApplication::Get().GetPlatformApplication();
if (genericApplication.Get() != nullptr && genericApplication->IsGamepadAttached())
{
return true;
}
return false;
}
Then finally uncommment/enable slate module depenecies within your projectname.Build.cs and reboot you editor before hitting compile.
YourProjectName.Build.cs
// Uncomment if you are using Slate UI
PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
Now you have a node inside blueprint to check if the gamepad is connected,
If you connect to the FCoreDelegates::OnControllerConnectionChange
delegate then you can be notified whenever a gamepad is connected/disconnected. Just make a function with the following signature:
void OnControllerConnectionChanged(bool bIsConnected, FPlatformUserId UserID, int32 UserIndex);