My first full iPhone game is finished and I’m testing on the device now. Everything is working except the frame rate has drop to between 3 & 6 FPS. It has been running at 65-80 FPS in the editor. I’m a little unsure on how/where to begin to find out what is causing the drop on the device. I’ve turned on the built in profiler to check the output in Xcode but not sure what to look for.
I’m using Unity3D 4.5.4 indie on iMac OSX 10.9.5 and testing on an iPhone 4 iOS 7.
Frame rate drops on playable levels.
Main, level select, settings & credit screens run at 31 FPS.
Game is a 2D top down shooter using sprite sheets to cut down on draw calls
Draw calls are between 4 & 5 ( 2 are from GUI text and explosion prefab)
Any suggestions on where I should begin to look would be great.
Do you have sphere with lots of polygons. If so back off the polygons, also how large are your texture files. I have a rule of 60 frames a sec(You set this in a Script)on my 2d side scroller and its as smooth as but I minimise the polygons and set the textures (Max Size and Format) optimal on the assets.
Are you saving data on the fly ?
Also do you have lots of sounds attached to lots of objects all trying to run ? If so try preloading them and pointing the audio objects to the one source rather than have them load and run individually creating multiple instances when needed on the fly. Disk load of audio could be slowing that down as well. Eg. The same explosion over and over. Preload the explosion audio and then get the objects to call a singleton to play it over from many game objects that need it. So the sound file is preloaded only once but called from many places and there is no delay in audio and less memory usage. I can expand if you have heaps of audio and are doing this. Just let me know. Also are you playing a load from disk soundtrack in the background. If so again load it up into memory and play it if it effects your frame rate reading the iOS hardware on the fly. An easy test is turn that off to see if the rate increases.
Another thing is Apple Metal API support will be built into Unity soon and that will give you a HUGE increase in polygon / graphic rendering as well.
Last but not least turn game objects/textures off until your frame rate comes back up and locate the culprit.
And also scaling objects will effect performance as well.
I find the profiler a bit not reliable currently, just hope it’s improved in version 5 especially when comes to mobile tests.
No point trying to check it on Editor as you will get results of your computer.
What you need to do is select “development build” and connect it to your mobile device (wifi profiler) which itself takes resources (this is what I been reading all day). Most of the issues I cannot solve as things like “Overhead” makes no sense and a number of other rare resource hungry features. Another thing I noticed is diry spikes when it comes to using Dynamic fonts and features such as the uGUI, which of course still in beta, but find buggy after 20 betas!
Good luck anyway…btw iPhone 4 and touch you will have worst performance even if they older devices sometimes it just does not make sense.
@CrystalDynamo I set my images to true color cuz it looked better in the editor but I’m going to try switching my images to 16bit and see how things look. I’m also using Everyplay to record the game as the player plays. Wonder if that could be sucking up resources too.
My game is a 2d top down shooter. I was able to get all assets on 3 separate sprite sheets. So draw calls are just 3 for all the art and another 2 draw calls for the GUI text and explosions (particles).
@PixelEnvision I’m using the internal profiler but don’t know what to look for. Anything that I should be looking out for?
Use profiler with the iPhone. Simply connect it to a development build.
Sort by GC Alloc, remove all garbage allocation you can find.
Pool, don’t instantiate.
Once you’ve done that, it’s time to look at graphics. The iPhone 4 GPU weaknesses are: fill rate and shader complexity. Assuming you’re using shaders from something like EchoLogin Core Framework, or unity mobile shaders for everything with no desktop post FX then the issue most likely will end up being too much overdraw. The solutions for that are: render to a lower resolution, or simply do not use too much transparency on top of other elements.
Since you’ve given no details, I can give no clear answers. You will find your questions have been answered repeatedly on these forums though. It’s common: new dev giggles and announces game’s done then at the end realises it runs like crap on mobile. That’s ok, just be prepared for at least a month worth of optimisation and lots of research to get it back up to 30-60.
You’re perfectly fine with 50+ draw calls on any mobile these days. Setting textures to 16 bit on this hardware will typically result in zero performance difference unless you’re pushing tonnes of 2048 textures through the eye of a needle: iOS is a platform that tolerates texture bandwidth abuse rather well.
no. Complete misunderstanding of what Metal actually is. If the bottlenecks are fill rate or shader complexity (which are usually the bottlenecks, yes) then it won’t make a shred of difference at all.
Metal is about reducing overhead, which includes driver overheads and boosting draw call performance. It might mean some shaders run a little faster as well, but really, if you’re throwing pows and square roots around in fragment shader like they’re going out of fashion or being fill rate bound then there’s nothing metal can do to save you. And these are typical problems when optimising for mobile.
OP’s 5 draw calls won’t magically change anything. It’s likely this isn’t even going to register. Need him to trust in profiler and importantly, understand what’s going on here.
Cool I was just going off the Metal Demo at the Apple conference and the Dev’s comment that was showing the demo. I assumed it was correct. I’ll have to google up more on it.
Basically more draw calls (think thousands instead of a hundred) and more CPU time. A draw call is currently performed on the CPU, sending data to the GPU to process. So less of that means the GPU waits around less and the CPU has more time to be abused by giggling programmers. Still vulnerable to physics limitations of heat and power ie - if the GPU can’t do more pixels in a set time, it won’t do more pixels.
Thanks everyone! I’ve compressed the image assets more like @CrystalDynamo suggested. This really improved the speed of the main, credits, settings & level select scenes. All the playable levels are still super slow. I removed Everyplay just to test if that was it and it only improved the frame rate by 1. Its a feature I really want so put it back in. I’ll take that 1 if it means sharing gameplay video.
I’ve started to use the internal profiler like @hippocoder & @MrEsquire suggested. I’ve included an entry below. It has on the highest collection total duration. I know what the draw-call, tris, certs & player detail are. Not sure on the others and what is a good or bad number for these. Going to google some of them now.
If anyone has insight to them, please let me know. Again, thanks everyone!
So it looks like cpu-waits-gpu is pretty high which means the cpu is waiting a long time for the gpu. Looking like its a texture issue. The 2D sprites used are from 3 sprite sheets which are PNGs with a transparent background. I read that its best to keep transparencies low for mobile. But sprites usually are generated from a sheet with transparencies.
OK. I found out whats causing the very poor frame rate but not sure how to fix it. There are 2 things causing the issue. The major cause is coming from sprites that are used to design the levels. I have 8 prefabs which are used to create the left/right “barriers” of each level. They have irregular shaped edges on one side which uses transparencies (kind of like flying through a bumpy tube). Here is an example of the kind of piece used. Removing them caused the frame rate to jump from 3-5fps to 20-25fps. The other issue was that I’m not using object pooling (yes, I know I’m stupid.) I removed the enemy spawners and the ability for the player to fire which gave me 5 more FPS bringing be to between 28-35FPS.
I’m going to start working on a pooling system which will help but I’m not sure on how to fix the transparency issue. I need to have these irregular shaped sprites to construct the level. How can I improve the over-draw on those sprites?
First ensure you’re using fast mobile shaders. Secondly, if you have Unity pro, then sprites are able to cut down on fill rate as they attempt to create a mesh that hugs the shape, so all that empty area isn’t also being drawn. Yes, invisible pixels still count as pixels to be drawn
If no Unity Pro you can do this by creating a mesh in a 3D package that better hugs the shape of the sprite.
Finally after the above steps you may want to render to a lower resolution for the iPhone 4, as that device is practically hopeless at lots of transparency (overdraw). I’ve used simpler terminology here but it’s better to make myself understood. You can do this by setting it to Auto (Best Performance).
No Unity Pro (wish I did) so I think I’ll be firing up Blender or Lightwave & try to create a mesh that fits those shapes. I did set to Auto (Best Performance) which helped a little. I should probably not worry about supporting iPhone 4 since 6 is out and iOS 8 won’t right right on the 4 or 4s but I’d like to try an support as many devices as I can.
OK well, I do insist you examine your shaders and post FX if any. You can try Core Framework for fast mobile shaders & pooling and Post FX for various post fx (but not too complex) (echoLogin - Asset Store) - alternatively try to use the mobile shaders and disable any post fx just for the iPhone 4 (leave enabled for stronger devices).
It’s just the iPhone 4 isn’t all that great (pretty much the same as the iPad 1). The 4S and above are awesome though and much more breathing room.
So I created meshes (with UVs) for those level pieces & tested it on the device. Test level runs at 22-28 FPS now. Only problem with this is the that the “curvy” edge to the pieces are pixelated When laying out the UVs for the meshes, I pulled in tight to remove the transparencies. Its not very noticeable on an iPhone 4 but more noticeable on the 5. I may tweak them a bit but its working.
Need to set up pooling next for the “bullets”, explosion prefabs & enemies. That should get me another 5-10 FPS.