[UE 5.8 / tvOS] Gamepad button RELEASE events never delivered when 2+ controllers are connected (Apple TV) — one controller works fine

Summary

On tvOS, gamepad button RELEASE events are never delivered once two or more GCControllers are connected. Presses arrive normally, but the key latches down, so any Enhanced Input action bound to Started/Pressed fires exactly once and never again.

With only one controller connected it works correctly. This is unavoidable on Apple TV because the Siri Remote is always a connected gamepad, so remote + any real gamepad = two controllers.

What Type of Bug are you experiencing?

Platform Other

Steps to Reproduce

  1. UE 5.8 project with Enhanced Input. Add IA_Jump (digital bool) mapped to
    Gamepad_FaceButton_Bottom, with Started → Jump.
  2. Package for tvOS (Development) and deploy to an Apple TV.
  3. Pair one gamepad (PS5 or Xbox). The Siri Remote is also connected, so the
    device now has two controllers.
  4. In game, press the jump button, release it, then press it again.

Expected Result

Jump triggers on every press.

Observed Result

Jump triggers on the first press only, then never again.

With LogEnhancedInput=Verbose, opening a menu 16 seconds after the last physical
press logs:

Key Gamepad_FaceButton_Bottom mapped to Input Action IA_Jump
will be ignored until released

FlushPressedKeys only flags keys it finds currently held, so Enhanced Input still
had the key DOWN 16 seconds after release. The release event never arrived.
UPlayerInput keys state per FKey rather than per device, so one missed release
latches that key for every connected controller.

Affects Versions

5.8

Platform(s)

iOS

Additional Notes

Controller count is the trigger (measured on device):
1 controller → works correctly
2 controllers → broken
3 controllers → broken
The second controller does not need to be touched, only connected.

The same project on iPad with a single controller works perfectly.

Already ruled out by testing on device:

  • Enhanced Input flush / bShouldBeIgnored (logged once, paired correctly with its
    clear)
  • bGameSupportsMultipleActiveControllers=True (made it worse: a second gamepad
    stops driving the pawn entirely, and the Siri Remote as PlayerOne still jumped
    only once)
  • Info.plist GCSupportedGameControllers = [ExtendedGamepad] only, MicroGamepad
    omitted (verified present in the shipped plist; the Siri Remote still
    enumerates)
  • Enhanced Input trigger configuration (with no release event, no trigger type can
    distinguish “still held” from “pressed again”)

Possibly relevant, not verified as the cause:
FAppleControllerInterface::SendControllerEvents() swaps the shared members
CurrentButtonIndex/PrevButtonIndex INSIDE the per-connected-controller loop, while
ControllerButtons is only [2][MAX_NUM_CONTROLLERS] and CaptureControllerState
writes solely to [CurrentButtonIndex][ControllerIndex].

Environment: UE 5.8.0, Blueprint-only project, macOS host, Xcode 26.6,
Apple TV 4K 1st gen (AppleTV6,2), tvOS 26.6. Full device logs available on
request, and I can rebuild and test a hypothesis on hardware in a few minutes.

Quick follow up. If I unpair my Apple TV remote and just use the PS5 controller the PS5 controller works perfectly, d-pad and left stick work with menu navigation and can control my character correctly - jumping and shooting. It’s only if I have the Apple TV remote connected doe the PS5 controller NOT work correctly. Initial launch of app, PS5 controller does not respond at all. Use the Apple TV remote to navigate menus a little and then I can use the PS5 controller - but can’t use d-pad for menu navigation as it goes to fast between options, so must use the left stick. Start the game and can only jump once and shoot once.

Update: I found the cause and have submitted a fix as PR #15183 against the release branch.

There turned out to be two separate bugs, not one.

The first is the one I suspected above. The swap of the button capture double buffer is inside the loop over connected controllers, so it runs once per controller and the parity depends on how many are connected. An odd number double buffers correctly, an even number ends up back where it started every frame, so the compare slot is never written and releases never look like a change. On an Apple TV the Siri Remote is always there, so one gamepad makes
two and that is the normal case.

The second one I had not reported. With the remote paired my gamepad did nothing at all after launch until I used the remote once. That is SetCurrentController. Apple can deliver DidBecomeCurrent before DidConnect, so it runs for a controller with no slot yet, never sets PreviousIndex, and then writes PlayerUnset onto whichever controller was player one. After that nothing is player one and SendControllerEvents skips every controller in that state, so everything goes quiet. Using the remote re-promotes it and the next pad press promotes the pad, which is why the nudge appeared to help.

Both are still present on ue5-main. Fixes and device logs are in the PR:

https://github.com/EpicGames/UnrealEngine/pull/15183

Hey Jumbolouko, :waving_hand:

I’m experiencing the exact same problem on Mac. As soon as I connect a second gamepad, any input on either gamepad is never released. This occurs in the game, in a blank project, and even in the editor window itself.

A fix for this from on high would be greatly appreciated.

Cheers.

Glad to see I’m not alone trying to develop on Apple’s platforms! I hope they resolve it and also resolve the Sign In With Apple and iCloud/CloudKit saving on ALL platforms and via Blueprints. It is a little frustrating.