How to optimize particle systems?

How to optimize particle systems? Let’s say there is a particle system on each bullet. And there are about 400 such bullets on the screen, as a result of which the FPS drops. But the particle systems are the same on every bullet. Is it possible to somehow combine a particle system so that it consumes few resources? It seems that this is what consumes more resources than physics.

Getting the usual questions out of the way…

URP, HDRP, or Builtin?
Can you use VFX Graph or only Shuriken?
Are you targeting mobile/VR/low-end or console/PC/high-end?
Are you already pooling the particle objects?

I assume your game looks like this, and you want to add trails to the bullets or something (warning AWESOME music):

If you really actually need 400 bullets on screen with their own systems, then you’re probably going to need to either do it on the GPU (VFX Graph might help, but it might not be configurable enough so you’d have to use compute shaders yourself) or else do the simulation in a Burst job and hand that off as a ComputeBuffer for the GPU to render. Advantages and disadvantages to both approaches.

1 Like

Yes, you can combine particle systems together.

Here’s a very abbreviated version:

public class Emitter : MonoBehaviour
{
    public ParticleSystem ps; // plug in via the Inspector
 
    public void Shoot(Vector3 startPos, Vector3 velocity)
    {
         ParticleSystem.EmitParams ep = new ParticleSystem.EmitParams
         {
              position = startPos,
              velocity = velocity;
         };

         ps.Emit(ep, 1);
    }
}

The essence here is that we manually emit a single particle using parameters that will work for the bullet. Every bullet comes from the same Particle System, and every shooter can reference the same script to shoot, so there’s only 1 particle system in total. You’ll need to calculate the correct velocity for the bullet to shoot it with the correct speed and direction.

Combining several particle systems together can be a very effective optimization in certain circumstances. The per-system overhead is relatively large, so quite a lot of gain can be had in combining and manually emitting.

For example, the below gif costs around 0.1ms on the CPU side: 0.05ms from the particle systems (system and subsystem) and 0.05 ms to calculate where to shoot and do the emit. And that half could be more optimized; this testing script has GameObject.Find and such.

That said, I’ve never tried it receiving collision callbacks, which will be the most costly part. For collisions I’ve only ever done custom collisions calculations myself for max efficiency.

Other particle system optimizations can be found here.

VFX Graph, as others have pointed out, may also be a viable solution.

2 Likes

Thank you! I need to figure out how it works.

Use 1 particle system to emit bullets, then pause and play particle system when shooting… This is what that has been used in the most games…
In other word, create a loop bullet shooting particle system
Your emission must be on the world space and not locale space (not rotating by gun rotation)

1 Like