Stop a particle system and dispose after last particle has died

I am trying to stop a particle system but only remove it from memory completely once the last particle has died. I’ve tried a few things with checking the active count but getActiveCount always seems to return the same number. Is there a good way to let the last particles die and then find out about it?

softCleanup() {
  // I have a class with many particle systems
  for (const { particleSystem, mesh } of this.particleSystems) {
    // TRIED THESE:
    // particleSystem.stop();
    // particleSystem.emitRate = 0;
    // particleSystem.manualEmitCount = 0;

    const remainingParticles = particleSystem.getActiveCount();
    
    // if any of the particle systems still has an active particle, check again in 100ms
    if (remainingParticles > 0) {
      this.softCleanupLoopTimeout = setTimeout(() => {
        this.softCleanup();
      }, 100);
      return;
    }
  }

  this.cleanup();
}

You may try to use particleSystem.particles.length
Example - https://playground.babylonjs.com/#0K3AQ2#3543

It looks like that works with CPU systems, but GPU systems don’t have that member data. Interestingly, when I use .getActiveParticles() with CPU systems it also works.

Is there no way to check remaining living particles with GPU systems?

One idea I had was to just read the max lifetime and set a timeout until that has passed, but I’m not sure what unit the lifetimes are in. Is it seconds?

As far as I see my solution works with webGL and webGPU as well.

I tried updating to version Babylon 8 since I was on version 7 thinking maybe they changed it, but I can’t seem to find the .particles property on an instance of the GPUParticleSystem class.

Now I begin to understand you better :slight_smile:
There are some differences in ParticleSystem and GPUParticleSystem.
This should work but doesn’t work, the observable seems never fired…

particleSystem.stop();
particleSystem.onStoppedObservable.addOnce(() => {
    // Wait an additional duration based on your particle lifetime
    setTimeout(() => {
        particleSystem.dispose();
    }, particleSystem.maxLifeTime * 1000);
});

Still this solution seems to work - https://playground.babylonjs.com/#0K3AQ2#3549

2 Likes

Ok, thanks for taking the time to look at this! I slightly modified the solution to use .isStopped() instead of _stopped because my IDE was complaining it was a private variable.

1 Like