[Niagara 5.1] Plexus Mini Tutorial

Plexus/Network style effects in Niagara Mini Tutorial

PlexusTuts

end result


So, I want to try and provide a sort of minimal setup for doing plexus/network tech-y kinda effects in Niagara. Just like the other mini tutorials, this is not intended to be a comprehensive one stop shop, but instead the smallest possible implementation, a surface level introduction that you can start building up from.

Only real prerequisite is to have basic Niagara knowledge. None of this will make sense if you don’t. There’s tones of good intro-into-niagara video’s out there, come back once you’ve had a look through those.

Source
The source will be the set of particles to span the plexus between, with our setup, this could be fairly arbitrary, in this case I went for a simple particle burst with high drag, and vortex/curl force pulling on the particles near the end of their live to add some motion.


Getting the nodes
Once we have a bunch of source particles, we’ll want to define connections, in this version we’re going for a 1 particle per connection system, so we’ll need 2 nodes to go between.
To that end, on particle spawn we will look for 2 parent particles, and save their id’s to be used for lookup.
image

We save the idea instead of the index, because the buffer will be shuffled and we need a consistent way to lookup the same 2 particles.

Note : Remember to enable persistent id generation on the Source Emitter!
image

We cannot get 2 random id’s though since they are somewhat unpredictable in their construction. So instead we get 2 random indices, and lookup and save their id’s instead.
You can try to solve identical parents here as well, but I prefer to just kill the connection in that case.


Updating the connections
Now that we have 2 points to connect between, we only need to find them and put a line between them.
Actually, putting a line between 2 points is already supported by the module SpriteBaseLine out of the box, so let’s just use that.
Note : SpriteBasedLine requires changing the Position, SpriteSize and Alignment Bindings.
Note : You also need to set the sprite Alignment mode to custom

To get the points themselves we can use the particle attribute reader again.
Similar to how our particle location module works, we’ll read the locations, check their validity and set some positions and the DataInstance.Alive parameter.
We save the positions into 2 output parameters Pos1 and Pos2 in this case so we can easily find them back in the SpriteBasedLine module.

We also calculate a strength parameter based on the distance between the 2 parents. This is to facility smooth fading as the particle move further apart. (I guess this isn’t strictly minimal, but it’s pretty common functionality in these types of effects)

An invalid parent will cause the connection to break. If we don’t do this, the connection will snap back to the center of the world.

And that’s it, shouldn’t be super difficult, but can be really powerful in the right context.
Hopefully that is helpful



More

I wanted to add a few more suggestions to get the gears turning.

  • These are sprites, so you can add some interesting shapes like lightning etc…
  • Check Length before spawning to take out connections that are too long or too short.
  • Partition using neighbor grid and find the closest n neighboring particles to create a cleaner non-overlapping network.
30 Likes

Haha thanks xD
That’s even more helpful than your reply!

1 Like

Thank you for taking the time making these tutorials. Really useful! <3

2 Likes

Very cool effect Niels, super useful! Especially how you get the particle IDs, something that I encounter a need for pretty often but wasn’t sure how to do.

Some clarity for others trying to follow this. I’m not as savvy with module scripting so this took some troubleshooting for me to replicate correctly (mostly…). Thankfully I knew JUST enough to figure it out :slight_smile:

  1. There is a Source emitter, and another emitter that is reading from the Source emitter. So, 2 emitters.
  2. I set both to have the same Spawn Burst Instantaneous numbers, and the same Lifetimes (otherwise you get wonky uneven results)
  3. The ‘Save Connection ID’ script is in the 2nd emitter, under Particle Spawn.
  4. In that module, depending on your editor build, there may not be a ‘Random Range Integer’ module. In mine it’s called ‘Calculate Random Range Integer’ (gotta’ love that stealth renaming). It works the same.
  5. The 2nd module script, Read Connection Position, should be in the Particle Update.
  6. The Sprite Based Line should be in the Particle Update as well, under the Read Connection Position module.
  7. In the Read Connection Position module I manually set the MaxLength to 500
  8. If you can’t find the Output param you need, make sure the module is selected, and look under the Parameters tab, under Module Outputs.
  9. Pay attention to the colors of the in/out lines in the modules. Some of them require you to manually set them to specific param types (ex. in calculating the strength param based on the distance between 2 points, I had to set my Length output manually to a float (right-click on the pin circle and select float). Make sure your colors match (that neon green is a float, yellow is a vector, red is a bool, etc.)
3 Likes

Glad you wrote it down. I’ve managed to figure out most of that stuff too, tho took me a considerable while xD

1 Like

Thanks for the tutorial!
This approach is quite interesting.

I wanted to add some more comments to the useful ones made by @kimber:

  • Be sure to set the “Sprite Rotation Mode” to “unset” in the initialize particule module in the second emitter. I just spent 15min wondering why my lines where messed up. :slight_smile:

  • I used “Spawn Rate” on both emitters instead of burst, and it works great for a long lasting effect. Using this setup you can set the lifespan of the lines to be longer than the source particles, so the lines only disappear when one of the two parents die.

2 Likes

Hi there and thank you soo much for the setup - it works really well!

I have a question about how can I check length before spawning to cut too long lines from the setup? I assume that I will need another scratchpad in Emitter Update with PAR, which compares distances between all particles in Source Emitter and clamp/bool based on a distance. Am I on the right direction? Thanks in advance!

Ideally you don’t check the distance to all particles, since that’s a really expensive thing to do.
Instead, since you’re fetching to 2 positions to span the particle between, you can find the length of the vector between the two:

length(Pos2-Pos1)

Then compare that value with min and max value

1 Like

It works! Thank you soo much for the quick reply <3

1 Like