I have created a spriteKit game and have a problem with performance issues.
Problem:
FPS gets stuck at 40.0
How and when does it happen
1. I have a pause function in my game by just using view!.scene?.paused = true Sometimes when I hit the home button, launch another app, then go back to the game the FPS gets 'stuck' at 40 and doesnt climb back up to 60.0. (Sometimes it does)
2. I have a 'sharing' Facebook and Twitter icon where when you tap on it you can post/share/tweet something on your account. This icon can be seen in the pause menu. After posting or returning back to the game FPS gets stuck at 40 FPS (And again, sometimes it does climb back up to 60. Sometimes it does not)
3. To clarify, this doesnt happen mid-game. This only happens if I minimize the app, launch the Facebook/Twitter icons, during reminder pop-ups.
Temporary fix
There is a temporary fix to this, which is to minimize the app and then launching it again. However, I wouldnt want my users to experience this at all. If possible Id like to eliminate this problem altogether.
What I have tried so far to fix this
1.Ive tried running this on instruments (time Profiler) but nothing really caught my eye. Thought I have to say I am quite new with instruments.
2. There is a similar question here but for him disabling UIKit items fixed it for him, and I dont have any of that.
3. I initially thought it was a SKShapeNode issue so I changed my sprites to SKSpriteNode. No help here either.
4. I have tried without the USB cable attached to the phone and tried running it using the Run button on XCode. No difference.
5. Ive tried rebooting device and laptop. Didnt help.
6. Tried this on multiple devices. Same issue.
Stats?
Game typically starts out at 20 nodes and 5 draws and can go up to 60 nodes 6 draws but it will actually still run smooth as long as I dont initiate any of the triggering methods mentioned above.
I have spent alot of time trying to find a solution for this. Changing codes and streamlining it. Googling it. I really need help on this one. I would really appreciate some help.
Update for comment #1
For you first inquiry
1) I have a SKSpriteNode as the pause button during gameplay for the user to pause the game if he wants to.
2) I have func applicationWillResignActive(application: UIApplication) {} in my AppDelegate.swift file that triggers a GameScene.swift function that changes a flag from true to false so that I know when the user goes out and come back in again. And I have my update block searching for that flag. If it is true, display the pause menu. However, this 40FPS issue happened before I added this whole pause/unpause thing. (The 40 FPS issue is what made me create the pause menu for this) (I know too in the latest ver. of swift that it will auto-pause when the app is minimized and unpause when I bring it back up.)
Related
I wrote this (what should be) crazy-simple app. (iOS 8.4.1, xcode 6.4, iPhone 6.) But it's not behaving the way I expected.
All it's supposed to do is display the current time, have the screen darken when face down on a surface, and never sleep.
I can supply actual code, and all sorts of investigative output, but here's the gist of it.
It has two NSLabels that display the time.
I created an NSTimer (1.0 secs) that calls a func that: updates the content of the two NSLabels, and calls setNeedsDisplay for both of them.
I set proximityMonitoringEnabled to true
I set idleTimerDisabled to true
At first glance the app seems to function properly. The screen darkens when put face down, and lights up when lifted. The time updates just fine.
The problem is that the screen will occasionally fail to light back up when picked up. It seems like, in this case, the device has gone to sleep while it was face down. (I've checked the console logs, and it's not crashing.)
I can post the full source, and a lot of other debug data if it's useful, but my first question is, have I missed anything obvious here in trying to prevent the device from ever sleeping? Or, is there some known issue that requires special handling?
UPDATE, as a result another post on this site, about a seemingly related problem, I now don't simply set idleTimerDisabled to true, I first set it to false, then true. Also, I added another NSTimer which toggles idleTimerDisabled to false then true every 20 seconds. Neither of these seem to have solved the problem.
???
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.
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.
I've also run into this. I can verify that it's a bug in Unity 4.3.x.
My 4.2.x builds process touches on device at 60Hz with TouchPhase.Moved on every frame.
My 4.3.x builds get 20-40Hz with TouchPhase.Stationary being emitted on dropped frames.
TestFlight history saved my sanity here.
Don't forget to file a bug with UT.
It's a real disaster. Sometimes it's lag and sometimes it's really smooth. It lags even when GPU and CPU utilization are below 10%. it's not Unity bug. I'm using cocos2d v3.
If someone found a cure, please post it!
I've been running into this as well. My current hypothesis which I still have to verify is that if you ask for a given frame rate (eg. 60fps), but your actually achieved frame rate is less than that (eg. 45fps) that this causes a timing/race condition issue between Unity requesting inputs from iOS at a higher frame rate than it actually is running at. However, if you set it to 30fps (at least in my UNity 5.2 tests with iOS 9.1) then you get a solid 30Hz of input. When I disabled a chunk of my game and it was running at a very solid 60fps, then I would consistently get 60Hz of input from the touch screen. This is what I have for now, but I have to prove this in a simple project which I haven't had time to do yet. Hope this helps someone else.
I found a potential solution to this problem here: https://forums.developer.apple.com/thread/62315 (posting here because it took me a lot of research to stumble across that link whereas this StackOverflow question was the first Google result).
To follow up on this, I got a resonse on my bug report to Apple. This
is the response:
"As long as you don't cause any display updates the screen stays in
low power and therefore 30hz mode, which in turn also keeps the event
input stream down at 30 hz. A workaround is to actually cause a
display update on each received move, even if it is just a one pixel
move of a view if input is needed while no explicit screen update will
be triggered."
In my application, using a GLKView, I set its
preferredFramesPerSecond to 60. Occasionally, my input rate would
randomly drop to 30hz. The response from Apple doesn't fully explain
why this would happen, but apparently the expected method of handling
this is to call display() directly from touchesMoved() while dragging.
I've subclassed GLKView and I set preferredFramesPerSecond to 60. On
touchesBegan(), I set isPaused=true, and start calling display()
within touchesMoved(). On touchesEnd(), I set isPaused=false. Doing
this, I'm no longer having any issues - the app is more performant
than it's ever been.
Apple's example TouchCanvas.xcodeproj does all drawing from within
touchesMoved() as well, so I guess this is the intended way to handle
this.
As far as I can tell, your best bet to achieve a smooth look may be to interpolate between touch events, rather than immediately mapping your objects to your touch position.
tl;dr: It seems just having a CADisplayLink causing any OpenGL context or Metal device to draw at 60fps can cause this.
I was repro'ing this on my iPhone 7 Plus w/ iOS 10.2.1.
I made a small sample simple app with a CADisplayLink with preferredFramesPerSecond = 60, and tried the following rendering approaches:
GLKView w/ display()
CAEAGLLayer, used as prescribed by Apple at WWDC (opaque, sole layer, fullscreen, nothing drawn above it)
MTLDevice
In each case, the render method would only clear the screen, not try drawing anything else.
In each case, I saw the input rate problem.
The following "tricks" also seemed to do nothing, when called inside touchesMoved:
Calling glkView.setNeedsDisplay() (with enableSetNeedsDisplay set to true)
Moving some other view
Calling glkView.display() (actually, seems like it can raise your input rate to 40 events per second. But it doesn't look any better, as far as I can tell, and seems wrong to do, so I wouldn't recommend it.)
I gave up, after running all these tests. Instead, I interpolate my object between the touch positions instead. So it's what I'd recommend, too.
But I figured I'd include my research here in case somebody else takes a stab at it and finds a better solution.
I am getting a strange behavior when I reopen my app after it loses focus from the home button. On the simulator the app screen goes black for 5 seconds or more before the application is resumed. On the test device, the application either does the long delay or quits entirely and resets to starting state. I have put NSLog debug comments in the “applicationWillEnterForeground” and “applicationDidBecomeActive” but these only appear after the long delay so I will assume for now that nothing in these functions cause this delay.
I am using the following components in my program:
* a Tab Bar Controller
* 2 Timers, the Map kit
* IP socket streams
* 24 ViewControllers strung together on a storyboard.
* quite a few background images and image buttons
I would happily post code if I know what parts of the program was causing this error, but as it is I am clueless. Has anyone else experienced this type of error? Do any of the components I have listed have a history of causing similar errors?
I was quite far in development when this bug was discovered and I did not test for loss of focus via home button during the incremental development process. Other, smaller projects (which used sockets and timers) did not suffer from the same bug on the same test hardware.
I am using “applicationWillResignActive” to disable the timers, and close the streams. I am using “applicationDidBecomeActive” to restart the timers, and reopen the streams. The delay is occurring before “applicationWillEnterForeground” and “applicationDidBecomeActive” is run. Further more I tried disabling the code that initiates the streams and timers, but this did not have any effect on the bug.
I am using xCode4.4.1, ios6, and am building exclusively for iPads.
It's possible that the debugger is playing tricks with your mind regarding when it shows that you hit a breakpoint and the code execution of applicationWillEnterForeground. I suggest you commit your most recent code to source control and start deleting sections one at a time till you see the behavior go away.
I am working on a research project that involves user interaction with an iPod. The application runs for approximately 10 hours, and I need to record the following information:
1) How many times was the screen touched?
2) For each touch, where was it touched? (Inside the button vs.outside)
3) What time was it touched? This would preferably be the time of day, but I can do back-calculations if this is not possible.
This information needs to be saved, and exported to a file that can be manipulated in Matlab, Igor, Excel,etc.
The application itself is very simple. A button in the middle of the screen flashes while playing a sound. When a touch event occurs inside the button, the flashing and sound stop for 30 seconds.
My questions is similar to this one from 2010 How to record all of the user's touches in iPhone app. The asker, however, did not provide the details for how he accomplished this, and I'm afraid I need a little more guidance than is given.
I'd be grateful for some advice, or if you could point me to the appropriate resources. I would especially appreciate it if you could also let me know the general area where the code should go. I'm still getting the hang of objective-C.
This problem has driven me crazy, it's been 5 days I'm trying to solve it. Here I am, desperate for a solution.
I am developing a simple game on Cocos2d. A loop method : -(void)update:(CCTime)delta gets called every specific interval of time.
This thing started happening just 5 days ago and god knows why. At any random point in the middle of the game loop, around 10 seconds (could vary from 5 to 20 secs) after the beginning of the game loop, it will just freeze, for no apparent reason. Instruments won't detect anything, debugger won't notice a thing. All I noticed is that the loop stops being called. No memory problem, or anything related to it.
the
There's no specific method called that's driving that freeze, which is being completely random. Same thing happens on iPhone, iPad, iPod touch, wether its the only app running or not, and wether its iOS 4.0 or 5.0... There are absolutely no leaks detected from instruments, no Zombie objects either.
I repeat, this is not a crash, just a freeze in the game loop.
PS: the music still runs in the background even though the graphics are frozen.
I am on Xcode 4.2 with iOS 5.0 and Cocos2d 1.0.1, running my game on iPad 1, iPhone 4, 3GS and iTouch 3g all of them on iOS 5.0.1. Same freeze....
Any ideas? PLEASE HELP!
Well, i know a sure fire way of 'stopping' all graphic processing with coco (ver 99.4), whilst the touch handling mechanisms are still perfectly working. I just checked back in an older version of a project and here it goes:
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setObject:nil forKey:#"key"];
I just added this method in one of the combat scene wrapup and exit scenes, and sure enough. What i get is a dead stall, no exception whatsoever, music and touch handling still working. The log still shows that my touch processing routines are handled AND called back. This had me stomped for a long bit, and i now "pattern" myself out of similar obvious mistake. If something like this happens in any one of your threads, the app will give you the 'freeze' bit. Hope you can find your root cause.
Look for any occurrences of message sends to methods whose name begins with "unschedule".
If that doesn't help, set a breakpoint in the CCScheduler class in the method "tick" once the freeze happens. If the CCScheduler doesn't "tick", find out why. If it still ticks, check if it still has any selectors in its lists. To do that you may want to set breakpoints in all the "unschedule" methods of the CCScheduler class to find out who is unscheduling methods and why.