Closed XuYicong closed 4 months ago
How did you figured out this. Awesome!
How did you figured out this
I was mainly analyzing the game's call stacks by sampling the running game. And I found some calls related to GameController
framework, but I don't have sufficient evidence to say that's the reason of the input issue. I kinda guessed things and tested a fix, and it just works. So I assume my guesses are right.
This is the call stack after applying this fix. The main queue executed a block that seems to be recording current controller input state (the [_GCDevicePhysicalInputGroup handleGamepadEvent:]
one). Although the handling here doesn't pass the recorded data into the game's private functions, I assume the data is stored somewhere internally, and the game is actively polling it every frame, in the UnityFramework
calls:
If we search for the word "GameController" in the sample plain text, we can find some calls like [GCControllerButtonInput isPressed]
under the UnityFramework
call, which gets executed every frame. I think it actually polls more than just ControllerButton
, but those calls happen so fast that the sample didn't capture them. If you sample it multiple times there are chances to capture it polling other controller keys like thumbsticks.
So here is the guess: Although UnityFramework
polls the controller state every frame, it's not actually checking the hardware state, but rather checking a controller state stored inside GameController
. GameController
just updates its stored state in a routine executed in main dispatch queue, which may not get called in some cases. So UnityFramework
may be checking every frame on an outdated state.
The reason I suspect main dispatch queue is from the experience of #83. The controller symptoms now are very similar to the keymapping symptoms then.
To verify this hypothesis, I just wrote this fix and tested it. I was actually prepared for the fix to fail, so that I can prove a hypothesis wrong quickly, but it seems to work. I'm even not sure whether or not it works in the way I think it is.
Fixes Playcover/Playcover/issues/1550
The issue is basically the same as #83. Testing and analysis shows that some games rely on GameController APIs (which in turn relies on main dispatch queue) to process controller input. But main dispatch queue may not be served in time for some reason.
CFRunLoop
of the main thread typically drains the main dispatch queue. It eventually calls_dispatch_main_queue_callback_4CF()
to do its work. In PlayTools, by calling this function every frame, the input can be processed timely. This is done via theCADisplayLink
, which is a timer that gets called every frame, originally designed for handling UI drawing routines.With this fix, I have played ZZZ with an XBox controller on my M1 pro Macbook, with ProMotion on, low power mode on, keymapping on, game in fullscreen and game fps set to 120Hz, for 4 hours and didn't encounter any input lag or unresponsiveness.