How to optimize hundreds of bullets ?

Hello. I’m sorry if the question was already answered anywhere else, but I didn’t found the solution to my problem.

Well, the problem is simple : I am creating a Shoot’em’up game, and my computer is lagging with ~300 bullets on screen and more. I’m searching a way to avoid this.

I tried to disable every bullet out of the screen to reuse them later, but it didn’t solve the problem.

I’m currently moving every bullet with a “bullet” script, translating them forward in the FixedUpdate(). I don’t use rigidbody but translations because I don’t need to manage collisions and I want beautiful trajectories. I that a bad thing ?

I don’t really need code or bug fixes, but I’m searching for advices to optimize the bullets. If you know how to properly manage a big amount of bullets, please help me.
Thanks.

I’m french, so if I made some mistakes, please excuse me.

Are you using colliders? If so, I don’t think this is the way to go. Probably need to do this with raycasting.

1 Like

I am using colliders (2D), yes. I only use box colliders to make it easier to calculate but maybe I have to not use them at all. I didn’t thought this way. I’ll try raycasting, thanks. If you have other advices, I’d be glad to hear them. Do you think that kinematic movement (Translate) is less good than physical movement (AddForce)?

Thank you, it’s way better with raycasting, and I don’t need to set a fixed timestep at 0.01 anymore to avoid fast bullets going through colliders without hitting them.

1 Like

What bottleneck are they generating now? Still high CPU time because of Physics or render batching?
I had similar issue and I solved it with raycasts too + moving all the rendering to ParticleSystem (my bullets use meshes)

yes. this is a bad thing. although you havnt given enough details to be 100% sure. It depends if your rb’s are kinematic or not.

Sounds like you need code despite thinking you don’t.

I stumbled upon this problem myself (although in 3D not 2D), so I can give you some ideas based on what I did:

  1. Each bullet is not an Unity object itself (with Transform, MeshFilter and all that), but just an instance of a class that is added to a list of projectiles in a manager script.
  2. The manager script handles the movement of all projectiles in bulk.
  3. The manager calculates collisions for each projectile only at the moment of that projectile’s creation and close to the predicted end of the projectile’s life. In the rest of the time, the manager just updates the postion of all the projectiles, without checking collisions for each.
  4. Each projectile’s lifespan is calculated based on its speed and based on that initial collision (which determines the flight distance and the possible targets that the projectile might hit later on, and stores those targets for later usage).
  5. Toward the predicted end of each projectile’s life, the manager begins to calculate collisions again, but only with the possible targets that were previously stored per projectile.
  6. Upon impact, the projectile instance gets destroyed and removed from the list, various visual effects are created, and the target hit gets notified about the impact.
  7. Since the projectiles are not Unity objects themselves, they can’t be drawn in the usual manner, so instead the manager draws them dynamically (by updating the vertices of a custom mesh which contains all the live projectiles visual data).

My system is quite complicated, but it works well with large numbers of projectiles.

2 Likes

So you’re using BoxCollider2D and not adding a Rigidbody2D which as you should know, means it’s a static collider i.e. should not be moved. You then proceed to move it. You then want to know how to optimize for lots of these.

Well first thing, do not move a static collider. :wink: Instead, add a Rigidbody2D and set it to be Kinematic. When you need to move it, use Rigidbody2D.MovePosition or if you are not interested in interpolation and nice collision detection during movement then simply set the body position using Rigidbody2D.position (never change the Transform when you have a Rigidbody2D attached).

Second, if you want it faster then use CircleCollider2D.

Third, if you’re not interested in callbacks but are detecting collisions yourself then do not use any colliders/rigidbodies on your projectiles (the fastest) and just move your projectile GameObject transform. You can then use 2D physics queries to perform checks to see what it hits (or will hit).

2 Likes

I see. I’ll try to manage the bullets with a manager. I am able to check collisions this way, but I still have to find a way to display the bullets without having a gameobject with a renderer.