- Home /
2D optimization help, im going crazy...
ok so...
I'm at the optimization stage of my game, its a 2D top down shooter as seen in the image
I'm testing it on a basic crappy android LGMS323 because I want decent performance on even the crappiest phones in order to cover as many people as possible.
My issue is the following: Once around 70+ zombies are visible on the screen like in the image below, my FPS starts QUICKLY tumbling from 60 to around 30-35. My draw call count is 8.
Each zombie has: Box collider 2D(size adjusted in real time with animation frames), Rigidbody2D(never sleep) a child containing: box collider, rigidbody KINEMATIC
The turret the zombies are colliding with contains: circle collider 2d, NO rigidbody(i don't know if rotating the turret counts as moving a static collider)
I have tried the following to fix the fps drop:
Removing all sounds from zombie prefab -> didn't affect FPS
Made zombie box collider2d constant size for all animations -> didn't affect FPS
deleting animator component to stop all animations -> didnt affect FPS
removing zombie rotation code(uses ATAN function which i heard was expensive) -> didnt affect FPS
playing around with build settings(i tried everything such as different rendering, different api levels, multithread toggle, graphics level, etc) -> didnt affect fps
removing applyforce from zombie -> didnt affect fps
changing sprite texture quality to lowest quality of "32" -> didn't affect fps
changing fixed timestep from .02 to .04,.05. even .1 -> didn't affect fps
played around with the physics2D,3D settings -> a bit over my head, didn't affect fps
I disabled collision of zombies with each other using ignore layers in the physics2D,3D options-> didn't affect fps!
Deleted the child from zombie prefab(which contained box collider and rigidbody KINEMATIC) -> gained about 15 FPS(but removes important functionality)
Deleted box collider 2D from zombie, -> gained around 10+ fps(obviously losing major functionality)
So there you have it... the only 2 ways i was able to increase fps was to completely get rid of the colliders which made my game mostly nonfunctional
The 2D collider is used for collisions with the turret as well as to facilitate natural bumping with the other zombies(no collision calls for zombies), and for bullets to hit the zombies.
The 3d collider is used to enable collision with a particle system flamethrower, since particles cannot collide with 2d colliders(unfortunately...)
I cannot think of another way to implement the features that the colliders provide.
Please help, I've really tried hard to do this on my own and I'm kind of stuck here. I was thinking of maybe replacing 2D colliders with Physics2D.OverlapCircle functionality, but I'm not sure how i'd know when to call that function unless i called it EVERY FRAME in which case won't it become even worse than colliders?
If i had Unity pro i'm sure the profile would help pinpoint what's causing this but I have only Unity free and it's SUPER FRUSTRATING!
I'd be more than happy to provide more information if i missed something important.
Thanks. :)
edit: some extra information just in case
I set Application.targetFrameRate = 60; VSYNC is OFF in quality setting All quality settings are set to MINIMUM
I guess you have Unity Free and not Unity Pro? The profiler would be a great help here (Pro only).
Also - try to run in Unity editor and try using the stats window (top right of Game-tab). Free and pro.
I've looked at the stats but have no idea what values would be bad and what would be good?
Someone correct me if I'm wrong but... 70 colliders stacking and colliding with each other sounds like A LOT. Especially on mobile.
70 separate colliders all around the screen might be no problem but with 70 box colliders all trying to get to the same place there could easily be 70x4 collisions to resolve each Update()
I'm not sure what you mean when you say "I thought any collision related calculations are called only on onCollisionEnter,onTriggerEnter, and that nothing is being checked regarding collision stuff at any other moment."
Checking collisions between objects is how the onCollision/onTrigger methods are called. The only way to know a collision happened is to check for it -- this isn't magic, after all.
Yes. As others have said, there are optimizations in place to help keep the calculations low, but the system still as to go through your colliders and do calculations. Once the physics system has deter$$anonymous$$ed a collision has occurred, it will call all the relevant methods (generally, anything with On at the start of it is a 'callback' method, and works similarly).
Answer by ChrisRob · Oct 15, 2014 at 07:26 AM
Hi Luniac,
I'd suggest three things:
If you haven't already been using it, the Object Pool (with setActive instead of Instantiate)
Data Locality (more efficient caching and linking between calls)
It certainly sounds as though what is causing it is tags, and high level to native calls and pointers. I'd recommend the 3rd article will probably be your answer with regards to asset arrays instead of pointer arrays. But the other two items will help too.
Good luck.
I do use pooling.
The data locality article is very interesting but I don't really see a way to implement the ideas from within unity, right? i do my best to prevent repetitive unnecessary calls from objects to objects, i generally have an if statement every frame to check if some more complex code needs to be executed
Looking at the gamasutra article: I DO use foreach loop in a few spots that can be easily changed to regular for loops, but i use them only in spots that don't run every frame. i already converted tag checks to comparetag() I did pay attention to a lot of the stuff in the article in my game. The nice part for me is that I specifically focused on making a VERY simple game, and it's STILL not done after a good 8 months. I learned soooo much stuff though, it's like night and day, winter and summer, but hey you don't become a self sustainable game developer overnight :) I guess the old advise of not overwhel$$anonymous$$g yourself with a complex game holds true as always.
The 2 biggest bottlenecks by FAR are continuous non stop 2d collisions between 50+ zombies which makes total sense, and the $$anonymous$$ECHANI$$anonymous$$ animation system.
I have already converted the animation system to legacy which reduced that footprint by over 50% i believe. Now all that's left is to $$anonymous$$imize the number of collisions between zombies which should work by freezing them for a split second or more after any collision. It doesn't affect gameplay in any big way but it should be the final push i need to have a solid 60 fps.
Answer by agora · Oct 05, 2014 at 07:19 AM
I ran into a similar problem in a mobile game stacking stones. each stone had a 2d polygon collider. once too many stones were stacked i lost frame rate immediately. My solution was to add a decay counter, once a stone was long enough on screen i changed it to isKinematic.
I don't understand your game mechanic enough but perhaps it will help.
good luck.
Ahh well I can't do that with the 2d rigidbody because the zombie is always moving, and the 3d collider is already kinematic…
Answer by luniac · Oct 08, 2014 at 06:46 PM
I also noticed setting multithreaded in the build options lowered fps by 5+
I'm gonna recode a part of my game so that the 3d collider is deactivated as soon as a particle interacts with it, this way there will way less active 3d colliders at any moment in the game, a lot less actually, so that should help. In fact i'm completely removing any interactivity between zombie 3d colliders, and will make it only particle to collider collisions. It'll make a little extra overhead because ill have more particle with collision enabled, but ill minimize it so that it's less than 100 totalor so collidable particles added.
The way i have it now is that a particle collides with a 3d collider, that collider becomes a trigger and zombie goes on fire, at which point another zombie 3d collider can collide with the trigger and also become a trigger and go on fire, and so on and so on. eventually when the fire disipates from any particular zombie, that 3d collider will deactivate so it cant set any other 3d colliders into a trigger and on fire. It was actually kind of elegant lol, i thought i was being proactive in utilizing one 3d collider for all that functionality by playing with the triggers.
But now the 3d colider can be deactivated the entire time the zombie is on fire instead of being a trigger, and ill just have the fire be a collidable particle like my flamethrower weapon actually. I was originally trying to lower my collidable particle count because i know its inefficient but i NEVER thought that it would turn out that the 3d colliders themselves were this inefficient, even as kinematic!
I'm still not sure how i'm gonna limit the 2d collisions between zombies, but technically speaking, since the turret won't be able to take too many hits, by the time enough zombies start colliding with each other, the turret will already be destroyed.
I'm really not sure any other way to not have the zombies not collide with each other, i definitely don't want them to overlap and ignore any collisions because that would just look silly.
I was thinking of implementing a non physics way of motion using transforms and pure scripting, but it just would just be over complicating things in my opinion at the moment.
I was thinking i'll just limit the amount of zombies on screen at any moment to maybe 50 or less, and if it's too easy i can make them faster.
I'm gonna play around a little more with the timestep after i'm done recoding the 3d collider part and see if maybe i missed a little fps boost somewhere.
Thanks for the help guys, ill definitely write back with my final solution and fps in case anyones interested.
setting the zombies to be able to sleep actually lowered my fps! i think having the zombies sleep awake sleep awake sleep awake so often is more of an overhead than just having them awake at all times!
I also found this: http://x-$$anonymous$$m.com/2013/11/unity3d-v4-3-2d-vs-3d-physics/
somehow they ran all those hundreds of blocks on mobile with decent fps, and it handled the collisions fine at 47 fps.
How did they do it?
I got access to the Unity profiler and guess what...
The mechanim animation system is a $$anonymous$$AJOR HOG. The two biggest performance drains were mechanim and the 2D colliders.
I converted all my 2d animation from mechanim to legacy using a simple script and now although the frame rate jumps around a little, it's almost always around 60 fps at all times, even when all the zombies are bunched up together!
I got another major idea. I'll freeze the zombies for a split second after any collision to prevent any continous collisions. That should solve all my problems.
Answer by MrSoad · Oct 13, 2014 at 11:12 PM
Are you caching your transforms. If you are not it is doing the equivelent of gameObject.find every time you move a Zombie. Have a look at this, it certainly won't hurt your frame rate.
private var tMy_Transform : Transform;
function Start() {
//Initialise vars.
tMy_Transform = transform;
}
function Update() {
//Whatever you want to do, just used this as an example.
tMy_Transform.Rotate(Vector3.up * fRotation_Speed * Time.deltaTime);
}
Thought I would check, no harm in mentioning it just in case...
Your answer
Follow this Question
Related Questions
High quality giving more FPS against low quality on android? 1 Answer
Add 2d rigidbodies to moving objects to increase performance or not? 1 Answer
Unity3.4 Mobile Terrain Lag 1 Answer
Colliders vs Callbacks: Which is better for performance in my case? 0 Answers
World canvas with screen space canvas performance mobile ? 0 Answers