Search code examples
unity-game-engineparticle-system

How to control particles directly while preventing the particle system from doing the same?


I have lots of same simple objects that are affecting gameplay, thousands of them! Well, not thousands, but really many. So if I make them GameObjects, the FPS decreases, especially when spawning them. Even with pooling. I should try a different approach.

You know that particle system in Unity3D can render many particles very fast. It also automatically controls particles, emits and removes them. But in my case, positions and lifetimes of objects are managed by game logic, and particle system is not allowed to do anything without my command, even reorder particles.

I am trying to use SetParticles method to control particles. It works in test project, where I use GetParticles first. I can even remove particles setting lifetime to -1, but can't spawn new ones. Also it does not prevent particle system from controlling particles.

I can disable emission so no particles will be created automatically.
I can set particles speed to 0 so they will not move.
I can set lifetime to huge number so they will not be removed.

I have an pool of Particle instances, to avoid unnessessary GC allocations. Objects receive a reference to particle when they are spawned, change it when updated, and set lifetime -1 and return it to pool when deleted. The pool stores this:

private ParticleSystem.Particle [] _unusedParticles;
private int                        _unusedCount;
private ParticleSystem.Particle [] _array;

_unused array and counter are needed for pooling, and _array stores all particles, used and unused alike, and is used in SetParticles call.

The main disadvantage of this method is that it doesn't work, probably because SetParticles does not create new particles. Also I guess it doesn't do anything with particles draw order, that's why it's poorly suited for bullet hell games where bullet patterns should look nice.

What should I do to properly disable automatic control of particles and properly setup direct control, with spawning and removing?


Solution

  • What you are looking for might be

        List<Matrix4x4> matrixes=new List<Matrix4x4>();
        for (...)
        {
            matrixes.Add(Matrix4x4.TRS( position,rotation,scale));
        }
        Graphics.DrawMeshInstanced(mesh,0,material, matrixes);
    

    On each frame you can just update positions, rotations and scales, and get all the instances rendered on the GPU in one drawcall (pretty darn fast compared to seperate gameobjects). You can render up to 1000 instances in one call using this way