"2D optimization help, im going crazy..." (118442)

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. :slight_smile:

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?

How are you instantiating your GameObjects in a scene? Do you do it as needed? Do you pool objects and requeue them in the pool for use when needed with perhaps a dynamic increase based off assuming n number of zombies but needed more than the pool provided?

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()

Anyone got anything? at this point ill take any idea to try out... i just dont understand how just the existence of the colliders slows down the game even if theyre not interacting with anything such as when i turn them off... i can supply the zombie script if needed...

4 Answers

4

Hi Luniac,

I’d suggest three things:

  1. If you haven’t already been using it, the Object Pool (with setActive instead of Instantiate)
  2. This article from Gamasutra
  3. 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 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…

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-team.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 MAJOR 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.

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);
}

i do cache my transforms.

Thought I would check, no harm in mentioning it just in case...

No of course not, thanks for trying to help.