How do you detect a second gamepad for splitscreen?

I’m building a local splitscreen multiplayer (which is completely optional), and it’s kinda stupid to just create a second PlayerController without actually checking there’s a second gamepad connected/receiving some input from second gamepad.

Everything Blueprints have to offer is just not enough to solve this (a pretty simple) task, so what do I do? Write my own C++ extension?

I’ve found the solution that works for now and I’m posting an explanation here for everyone to use it and build upon.

I’ve subclassed AGameMode, since I do all my player management there, and put this in BeginPlay:

OnControllerConnectionHandle = FCoreDelegates::OnControllerConnectionChange.AddUFunction(this, FName("OnControllerConnectionChange"));

with OnControllerConnectionChange being declared like this:

UFUNCTION(BlueprintImplementableEvent, Category = "Input", Meta = (DisplayName = "On Controller Connection Change"))
void OnControllerConnectionChange(bool Connected, int32 UserID, int32 ControllerID);

Now, OnControllerConnectionChange fires every time a gamepad or any other controller recognized by Windows is plugged in or pulled out.

Note: UserID is pretty much useless right now, as it always returns -1, but ControllerID will always return the index of the controller, starting from 0. If you plug the second gamepad, it will have index == 1, and if you pull out the first one after that, the index of the second won’t change, so you can (almost) safely tie ControllerID to PlayerController index.

Another thing - editor is completely unreliable when testing this. First of all, the event fires for every controller plugged on the game launch, so you can actually launch splitscreen right on or safely tie ControllerID to player indices, but only in Standalone mode or packaged builds, it doesn’t in the editor. Second, pulling out/plugging in during PIE fires the event 3 (three) times. Third, and it really grinds my gears - sometimes pulling out/plugging in silently crashes/closes the editor.

Don’t forget to call Remove for OnControllerConnectionHandle on EndPlay so you don’t crash anything:

FCoreDelegates::OnControllerConnectionChange.Remove(OnControllerConnectionHandle);

I’m still working on exposing input events from second gamepad without creating PlayerController specifically for this.

(You should also check out FCoreDelegates, it has lots of interesting stuff not exposed to blueprints.)

2 Likes

Exactly what I looked for!! Thanks!

For those finding this from Google; as of 5.1 this approach has been deprecated.

The updated solution:

1 Like