Spikes after half minute of running
Hi. I am making my 3d game but unfortunately i have spikes (fps decrease) after some time of running on android. Mechanics: the game like fit in the hole. Player- Parent gameobject with atteched controller script is moving forward along Z axis with changing its potision in update (i tried to attetch rigidbody component and set some velocity. had the same lags). It has some children that are switching on/off with setactive(true/false) when u press button. Any time only one is active. Child object has mesh renderer and some collider (mesh colliders are convex). MainCamera is a child object of Player (moving together). There is another gameobject pull of walls (30-60 object with atteched trigger box colliders and control script). Most part of them is non active. (they are turning on/off with setactive(true/ false) 3-5 object at the moment). Control script has OnTriggerEnter/Exit. Then the player passes the wall is turning off. For some time everything goes well, but then it starts lagging. If i turn off the display and wait for some time ( 2 minuts) laggs are gone, but the story repeat. If i turn off the display for a moment its still lagging. Immediately rebooting the game not helps too. Its like the device (some android phone) is collecting smthg for a moment and then it starts. Once on sumsung s6 i remove lags with holding down my finger on the display. I tried to switch on/off vsync. Removing Canvas with scores/ buttons/ menus only increase normal running time. I tried to remove all physics components and OnTriggerEnter/Exit. Using GC.collect. No matter. Lags are still there. Profiler shows strange behavior of Gfx.WaitForPresent what could it be?
Answer by Max_Bol · Dec 15, 2016 at 02:35 AM
A quick note. You got to put 2 breaking space to have create paragraph here. Reading your question was quite painful. Not counting the amount of typing errors that made it even more a troublesome task to accomplish.
Lag Spikes could be a result from many many many many things.
If you could share some screenshot of the scene when the spikes occur and when they are not, it could help at seeing what's different between each and what might be the cause of your problem.
Gfx.WaitForPresent is the process where the device is "ahead" and got nothing to do in the engine. It's kinda like "keeping some memory available". It's usually related to either VSync or when the display and calculation of the engine aren't synchronized.
Turning off VSync in the engine option might not work if the device force it on. Smart phone have an inner-limiter which limit the framerate regardless of the application (usually at 60). Your Gfx.WaitForPresent could be related to that.
At the same time, the issues with smartphone is that they have limited shared memory. They don't have actual GPU that has their own dedicated memory, but instead takes from the RAM pool. It's a slower process and more easy to clogged up.
Still, what seems to be (with lack of details) the cause of your problem is 2 things:
When you activate "everything", you're clogging up the available memory and it lags.
When you deactivate many things, you're clogging up the batching/cache and it lags.
The first one is the usual lag due to having too much managed by the phone and the second one is that you request too many changes quickly that requires the batching/cache to be updated and the phone has a problem recovering. (Kinda like how you can't move up from ignition to 300Km/h with a car in a sec.) The phone processing power might have relatively high capacity, but it's nothing instantaneous.
The way you got to plan your game on a phone is by making sure the phone has all it needs before it needs it and that it's already within the memory. SetActive() is the complete opposite of that as it's like a switch instantly calling and turning off calls. The best example I could come up with is if you had a game with enemies prefabs. On PC, you could instantiate those enemies on the fly and it wouldn't clog up the memory that much. On a phone, it would be suggested to, instead, keep a first instance of each enemy outside of the "game field" so that the phone can store and keep its related data active at all time.
Why are phone unable to have their processor as fast as PC when the numbers supposedly shows the contrary? Simple answer : Energy consumption. If you ran your phone with a 250-300 watts like a PC does, it could manage things a lot faster... but with the current batteries, it would drain all its juice in 30-45 min max (not counting the heat of the device.) You might find a phone that has a big whooping 8GB of RAM, but it processing power will still be that of a PC that might have 1GB-2GB max. The remaining 6GB-7GB is only useful for storing temporary voluminous data... not constantly changing it. My guess is that your project currently exceed the processing power of your phones or/and doesn't have a constant fixed amount of information being used.
Think of your game like a washing machine. When you launch a scene, you have to make sure as many thing in the scene are set "in the tub" (memory), then you start the spinning (Updates). You got to remove or add as less as possible during the spinning because, each time, you stop the machine to add or remove the pieces. This is what Occlusion Culling (in Unity) does. It's not just "turning" stuff off, it also keep their relevant data in memory. It's like a "unspinning" zone in the washing machine's tub. SetActive(), on the otherside, is like if you were removing the part from the tub. If you try to put it back inside, the tub entry might be too small so you do it piece by piece and it takes longer that's when Gfx.WaitForPresent seems to be the cause (while it's not).
One thing I noticed is your "Physic.Processing" is relatively high. This is mostly due to your usage of Triggers. Whenever possible, instead of using triggers zone, you should use a custom distance checker that does its check 2-4 times per secs. This will reduce the load on your physic.processing by around 40%-60% while raising the behavior.update by less than 0.01% per checker. (with 30-60 trigger, that's a trade of 15%-18% off from your physic.processing for 0.3%-0.6%... maybe 1% max onto the Behaviour.Update)
Trigger Collision box aren't something you use in numbers left and right permanently. Those are useful for short and precise collision effects such as bullets, explosions or other "quick temporary" things. Otherwise, they are like constant-per-frame calls of Coroutines that get "every" gameobject in the scene that has a collision component each frame and check up if there's a change from the last frame with each of them.
Your answer
Follow this Question
Related Questions
Device.present causing unexplainable slowdown 3 Answers
Android apk lags on all devices exept of mine 0 Answers
My game are really smooth on Unity test but really really lagging after build on Android 0 Answers
Sprite not rendering well on android 0 Answers
Physics2D.FixedUpdate and Device.Present lag spikes in profiler 0 Answers