Niagara chain physics and collision on permanent particles

This is kinda a response topic for a rope physics tutorial by @cAyou back in 2020. Some asked about if it can support collision and cAyou answered that they could reference the chain example in Epic’s content examples.

First, the chain example seems to only works with Analytic Plane collision. GPU Distance Fields collision will make the particles stuck to the origin (0,0,0). Second, I referenced that chain example and wrote a much simpler (but less accurate) chain physics without Simulation Stage or Calculate Accurate Velocity in UE 5.1.

Initially it works with GPU Distance Fields collision, but the problem is that at some point, some particles are being killed suddenly, even though I have already unchecked “kill particles when lifetime has elapsed”. The more the particles collide with the DF the more likely of the sudden death of particles, which breaks the chain physics because each particle needs to read the position of the neighboring particle. Analytic Plane again is the only option to avoid unexpected dying of my particles, or I can fall back to CPU sim and Ray Traced collision since I am not using Simulation Stage. (Actually I wouldn’t for the cost.)

In this video, the ribbon is composed of 40 particles, but at 0:19 the particle count begins to decrease, breaking the ribbon.

I am sure this is not caused by my chain setup. I setup another Niagara system with permanent particles and use only the built-in Curl Noise Force, Drag, Gravity Force and Collision modules. Again, particles randomly die at framerate hiccup.

I am curious if anyone else has similar experience of unexpected particle death by distance fields collision and knows anyway to avoid it.

Finally Merry Christmas

2 Likes

So it turns out that the dying of particle by DF collision is that the particle penetrated the surface for too long. This is more likely to happen against mesh with sharp edges like cube. Increasing the particle collision radius scale can make it less likely to penetrate. (I set them too low previously.)

Enable Rest State seems to be able to delay the inevitable, especially when the particles are not being moved drastically. Still it is increasing the collision radius provides the best improvement.

Because there is still risk of particles dying unexpectedly, I also updated the whole setup to reset the emitter (replacing Burst Instantaneous by Spawn Per Frame) and particle (adding Kill Particles) as long as the current particle number does not match the predefined burst count.

4 Likes

A rather unfortunate situation with DF collision again. The method I talked about in the last reply only works against static/immovable colliders. If the collider is movable and crushes into the particle fast enough, especially when the particle is sandwiched between 2 colliders, the particle is as good as dead.

Unless I can convince Epic to revise the core of the particle collision function to absolutely preserve all particles, the last resort would be writing my own pseudo-DF collision module, but this would be too laborious and is way out of my scope of this little experiment.

What if you switch to non-infinite particles and just continously respawn particles?
I assume you’ll run into the same issues?

I just looked into the DF collision module and I cannot find anything that would kill particles (except for aging rate, which I assume you are not using). So this is quite odd.

Your hack with checking the amount of allowed particles and if < than that, respawn them; seems still viable? Or did this not work?

(I couldn’t attach any video previously because my internet was under maintenance.)
The chain setup requires reading neighboring particle, otherwise it would return a NaN and break the whole thing. IOW it really doesn’t matter whether I use infinite lifetime particle or not. Infinite lifetime particle only makes it more obvious that particles are being killed by DF collision penetration.

No, there is no “kill occluded particle” option, unlike Depth Buffer collision (Depth Buffer collision is way too funky to work with anyway). On the other hand CPU Ray Traced collision is absolutely cool with surface penetration as demonstrated in the embedded video at 0:51.

Albeit lack of concrete evidence (practically impossible to verify with Niagara Debugger), my guess is that surface penetration in DF collision would result in NaN of any particle attribute (most likely Position), and when the engine detects this abnormality it just deletes that particle at once. I have my suspicion because I once created a vertex culling effect shader in Unity with division by zero, a very horrendous approach thankfully was never shipped.

To make it clear, the DF collision killing particles has nothing to do with my chain setup. Just create a new Niagara System, add the default Fountain emitter template, add Distance Fields collision to Particle Update, add the NS to your level and move it inside any collider with closed geometry.

My hack of resetting the emitter works, it’s just that the chain effect wouldn’t live happily with movable collider in DF collision.

1 Like

SDF collisions are meant to be good enough not perfect, so I don’t think there’s any way to get around it with the default modules.
But if you use a custom module you can sample the sdf manually and make your own decisions. Seems like it would be ok to just move the particles out of the negative part of the sdf in your usecase

1 Like

Yes, I eventually wrote a custom SDF collision module with Query Mesh DF GPU, tried to keep it as simple as possible. It’s nowhere as precise as Epic’s collision module (the usual DF resolution issue), at least my own module no longer kills the particle. I can live with this happily right now. :smiley:

Next step would be attempting a chain system with 2 anchors instead of 1.

5 Likes

Glad you were able to solve it! I like your ribbons :slight_smile:

Hi there! I was wondering if you did managed to create two anchor points, and if so did it break your collision module or it was just fine? :open_mouth: if it is fine, I was wondering (if you’re willing to share) what is the main logic behind the collision module?

I partition my particles into different groups and use that group index to look up the desired socket of the skeletal mesh. I use my own module to partition my particles (which is largely based on flipbook grid partition logic), but you can use the built-in “Partition Particles” module. I haven’t tried this module myself, but someone has made a tutorial about it. (Due to certain circumstance I prefer not to link any tutorial of that author on this site. Pardon me.)

The custom collision is just to get the boolean value from “is inside mesh” output of “Niagara Distance Field Collision” node. If so it returns the collision position, otherwise the original position value.