Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

touchesMoved called at irregular intervals

I'm making a game for iOS where you mostly drag big objects across the screen. When I run the game on an actual iPad/iPhone for a while (continuously dragging the object in circles across the screen) every 5 minutes or so the dragged object goes all stuttery for about 10-30 seconds. Then, it goes back to moving silky-smooth.

Visually, it looks like the game's frame rate dropped to 15 fps for a while, but in actual fact it's running at rock-solid 60 fps all the time. However, I noticed that the only thing that doesn't move smoothly is the dragged object, while the rest of the game is all running perfectly smooth.

This led me to believe that the stuttering is related to the touch input in iOS. So I started looking at touchesMoved, and saw that it's normally called every 16 milliseconds (so touch input runs at 60 fps). So far so good.

Then I noticed that when the object starts stuttering, touchesMoved starts being called at weird time intervals, fluctuating wildly between 8 milliseconds and 50 milliseconds.

So while the touchscreen is in this weird state, sometimes touchesMoved will get called just 8 milliseconds after the previous call, and sometimes it won't get called until 50 ms after the previous call. Of course, this makes the dragged object look all choppy because its position is updated at irregular intervals.

Do you have any idea what could be causing touchesMoved to stop being called at regular intervals, as it normally does?


Bonus:

-Whenever I tilt the screen to force the screen orientation to change, roughly 70% of the time the touchscreen goes into the aforementioned state where touchesMoved starts being called irregularly. Then after 10-20 seconds it goes back to normal and everything looks smooth again.

-I've tried this on two iPads and two iPhones, with iOS 6 and 7, and the issue appears in all of these devices.

-An OpenGLES view is used to display the graphics. It syncs to the display refresh rate using CADisplayLink.

-The Xcode project I'm using to test this has been generated by the unity3d game development tool, but I've found several non-unity games where the same issue appears. this appears to be a system-wide problem. note I'm measuring the timings in objective-c using CFAbsoluteTimeGetCurrent, completely outside unity.

like image 388
user3216310 Avatar asked Oct 20 '22 16:10

user3216310


1 Answers

This is not a bug in Unity.

Something inside the OS is getting into a bad state and the touch-drag messages stop flowing smoothly. Sometimes you'll get multiple updates in a frame and sometimes you'll get none.

The issue does not happen on iPhone4 or below, or if the game is running at 30Hz frame rate.

I experienced this bug while using an in-house engine I'd written while working at a previous company. It first manifest itself after upgrading the UI system of a scrabble genre game, where you drag the tiles about on the screen. This was utterly bizarre, and I was never able to pin down the exact reproduction steps, but they seem to be timing related, somehow.

It can also be seen on Angry Birds (unless they've fixed it by now), and a variety of other games on the market, basically anything with touch-drag scrolling or movement. For Angry Birds, just go into a level and start scrolling sideways. Most of the time it'll be silky smooth, but maybe 1 in 10 times, it'll be clunky. Re-start the app and try again.

A workaround is to drop the input update frequency to 30Hz for a few frames. This jolts the internals of the OS somehow and gives it time to straighten itself out, so when you crank it back up to 60Hz, it runs smoothly again.

Do that whenever you detect that the bad state has been entered.

like image 91
user3391642 Avatar answered Oct 23 '22 21:10

user3391642