I have a particle system and set the emitRate to a low number, the particles start appearing at the desired rate, but they always speed up until the particle system is at capacity. As far as I understand, new particles are indeed being emitted at the set rate, but also the old ones are being re-emitted, each one as soon as it dies, until they are all flying at once.
Perhaps I am missing something. Is there a way to have the recycled particles re-emitted only on an as needed basis? This way the emitRate would have a more meaningful relationship to the ongoing appearance of the system. I want to be able to dynamically set the emitRate, and have a visible effect when it is lowered.
Hello, could you create a playground highlighting the issue ?
I bet @PatrickRyan who loves particles can help providing some guidance.
@IIerpos I would also love to see a playground because emit rate should not change unless you have an emission gradient in the code after setting the emit rate.
Hi guys. Just a note… I struggled with this situation, too.
https://playground.babylonjs.com/#PU4WYI#107
I wanted the yellow box to remain easily-visible thru the particle spray, even after 10 minutes (consistent emit rate) but… there’s stuff I didn’t understand. Deltakosh tried to pull my head out of my butt… during a conversation that started here.
It’s seemingly complicated… for me. I am killing-off MANY particles via .maxLifetime, so in my thinking, the particleSystem cannot ever “saturate” (reach max particles). I am aging the particles to death… faster than the climb to saturation.
But that’s not the way it works. Read that reasonably-short conversation between Deltakosh and I, and maybe it will hold some answers. (no promises) After that discussion with Deltakosh about emitRate… I realized I don’t yet understand it, and have assumed that I did.
Most times, I just “blow off” max particleSystem capacity… setting it to any big number and moving-on with my bad coding. But… there is stuff to ponder… about max capacity and particle ages/recycling.
I think I understand how the system works; the problem I’m having is part of the design, not a bug. But as the playground example demonstrates, you can’t have a particle system in which the total particle appearances (which includes emitted and recycled particles) diminish over time. The total capacity is set in the constructor, and is not dynamic.
Does the answer lie in the activeParticleCount setter? I haven’t found documentation on this.
You can manually control how many particles are created with the manualEmitCount property:
https://doc.babylonjs.com/babylon101/particles#rates
In this case the number of particles given by the count are emitted and there are no further emissions of particles.
Yes, this is true. My problem is that, at any given moment:
visibleParticles = newParticles + recycledParticles
I can make “newParticles” any number >= 0. But I cannot decrease “recycledParticles”, therefore I cannot decrease “visibleParticles” over time, which is what I want to do. Does that make sense?
Thank you all for your responses, by the way!
Hi DK. Our friend is using GPU particles, so no manualEmitCount available.
@IIerpos , let’s set-up a testing playground with non-GPU particles, and some .manualEmitCount (MEC) work. I also went to standard JS.
In this PG, we start with 100 MEC every 1/10 second, and reduce the count by 1/4 particle every 1/10 second, too. So every 4/10th of a second, we reduce visible particles -1.
I know, weird numbers… adjust at will.
After you get the emit rate under YOUR control (via using .manualEmitCount) … you get more adjusting powers. I’m not sure if this will work for you @IIerpos , but maybe.
Thanks buddy! I missed that point.
I’m afraid we cannot control the GPU as much as we can with the CPU (for perf reason)
Thanks, Guys. I think that answers my question. Wingnut’s solution works, although it probably would kill performance for my application. I guess the kind of thing I am looking for is to disable the recycling altogether, or somehow emit, new or recycled, only when the number of live particles goes below a dynamically settable number. Maybe Babylon 4.2?
Good. It was actually Deltakosh’s solution. I just activated the correct type of PS for his idea to operate-within.
@IIerpos …if you are willing to STAY in CPU-particles-land, then you MIGHT have some more power over recycled particles. Take a look at this.
In lines 18-58… are 3 functions… one for startPosition, one for startDirection, and one for updating. I THINK they are currently shown… in un-modified state. In other words, the BJS lib uses the very same code by default.
In lines 85-87, you can see the three “custom functions” get installed in the particleSystem (thx to deltakosh for making these easy function-over-ride properties).
Up in lines 40-45… in the custom updater func… you can see some mention of particle age and recycling. You could change that… right there… perhaps make the particles do as you please. It might be useful to learn the properties on a particle base-class object.
And the custom startPosition function… might also be hack-able. Put those 3 custom funcs into YOUR PS code… and take the 3 installer lines (85-87), too. CPU particles have some advantages over GPU.
Keep in mind that the updater func runs very fast and continuous. The other two “customs” are quick, too, so don’t put a quadrillion lines of for/next loop in any of them, or you will bog into the local swamps, perf-wise.
Thanks again; you guys are the best! Another thing that I found to work, that allows for GPU usage, is to play with the activeParticleCount property. It’s not perfect (you can see a few particles die before their time as their numbers are culled without mercy ), but it achieves the effect I’m after.
Hey, and may I ask what the best approach to achieving the same using TypeScript would be? I have been trying to bind the update function to the ParticleSystem class, so that I could access internal variables in the function (like _scaledColorStep), but I have so far been unable to access the parameter (this or otherwise).
// modified code
const particleSystem = new ParticleSystem(‘ParticleSystem_01’, 100000, scene);
…
particleSystem.updateFunction = function (particles: Particle) {
for (let index = 0; index < particles.length; index++) {
const particle = particles[index];
particle.age += this._scaledUpdateSpeed;
if (particle.age >= particle.lifeTime) {
this.recycleParticle(particle);
index–;
continue;
} else {
particle.colorStep.scaleToRef(this._scaledUpdateSpeed, this._scaledColorStep);
particle.color.addInPlace(this._scaledColorStep);
if (particle.color.a < 0) particle.color.a = 0;
particle.angle += particle.angularSpeed * this._scaledUpdateSpeed;
particle.direction.scaleToRef(this._scaledUpdateSpeed, this._scaledDirection);
particle.position.addInPlace(this._scaledDirection);
this.gravity.scaleToRef(this._scaledUpdateSpeed, this._scaledGravity);
particle.direction.addInPlace(this._scaledGravity);
}
}
}.bind(particleSystem);
r
_scaledColorStep is not public but you could cast as any in TS to access it despite not being recommended. Another approach would be to managed the same parameter in your code to prevent the need of private access.
Thanks, and I opted to use any, as calculating the value outside the class seems redundant. Pardon me for a mostly TypeScript question.
r