Best approach to have collisions between Niagara particles and semi-transparent Procedural Mesh?

TLDR : My goal is to make some Niagara Particles interact with a Procedural Mesh Component. Ideally, I would like to be able to use both fluid simulation and classic particles collisions, with GPU simulation, and transparent materials. My only almost fully functional workaround is export the mesh to .obj and import it back in the project, and manually place it in the scene. It is not ideal, and transparency does not work. I’m looking for some insight on how to approach this subject.

I am a beginner at using Unreal Engine, and even more so Niagara and the Procedural Mesh, so I have some needs, but struggles come with them.

I am using UE 5.0.3.

After looking around a little, my understanding is that :

  • Niagara Fluid Simulation only enable interactions with static meshes
  • Niagara Particle Collisions only works on opaque meshes with GPU Sim
  • GPU Collision Type Distance Fields only works on meshes with precomputed (before runtime) mesh distance fields (haven’t explored that one much, not really sure, maybe I could trigger the calculation at runtime somehow, cf later my struggles with static mesh creation)

My first goal was to convert a Procedural Mesh to a static mesh at runtime, and make it work somehow.

My first workaround was exporting a .obj file, and importing it back in UE. It works, if I drop the created Static Mesh in the scene and give it the actor tag “collider”, the particles collide with the mesh.

The issue is that I do it with a button in the details panel and the export location and import parameters popup. Ideally, it would all be transparent and smooth :
end of procedural mesh creation → static mesh conversion → physics interactions.

The main advantages of this methods, though, are that the collisions are correctly set, the mesh distance fields are calculated, and it works with both particle physics and fluid simulation.

So, option 1 is to somehow do the whole export/import in code or blueprint, storing the mesh in a temp location and deleting it at the end. It seems inelegant though.

As I was looking further into the matter, I found this post :

I did a small modification to @newohrim 's solution, converting their function to be static and usable in blueprints. (Basically the signature of the function now looks like this)

UFUNCTION(BlueprintPure, meta = (DisplayName = "Convert Procedural Mesh to Static Mesh", Keywords = "Convert Procedural Mesh to Static Mesh"), Category = "Test")
static UStaticMesh* ProcMesh2StatMesh(UProceduralMeshComponent* ProcMesh)

I use it like this :

Surely enough, the function works to create the mesh in my setup. However, I can’t use the generated mesh to collide with the fluid simulation systems, collider tag or not. In fact, there seem to be no collisions at all generated with the mesh. I made sure to take the steps given in newohrim’s post, and it seems like the array ProcMesh->ProcMeshBodySetup->AggGeom.ConvexElems contains no element after the line NewBodySetup->AggGeom.ConvexElems = ProcMesh->ProcMeshBodySetup->AggGeom.ConvexElems;, so my issue might resides in my generation or blueprint.

I haven’t dived too deep in how the fluid simulation systems in Niagara work, and what they collide with, but I assume it to be the Simple Collisions.

However, the generated meshes, collisions or not, if given an opaque material, work with the particle collisions with the “GPU Depth Buffer” collision type (but not the distance fields collision types).

So, this is option 2, but it comes with (at least) two important flaws : it only works with opaque materials, and it seems to only works with the depth buffer collision type (which is not great, the particle are killed as soon as they are hidden). But, assuming I fix my collisions problems, it would be cleaner than option 1 (in my opinion).

The issue is, though, that I struggled hard with the collisions, and made this post to find a lead : How to add K-DOP collisions in blueprints in UE5 ?

@jwatte insight is that what I tried to achieve, re-generate collisions, mimicking option 1 in a cleaner way, at runtime, is hard, if not impossible for now.

So, as I reach a deadlock, I’m wondering if there may be an option 3, maybe involving passing a custom depth buffer to my Niagara system to solve the transparency, or something else. Anything, really.

Thanks in advance for any insight about this !

All I can say is that I’ve used procedural meshes as floors, and they seem to work fine for collision for me. That’s for physics collision, though – I have not attempted this with Niagara or fluid simulation. You may need to dig into the C++ code and figure out what’s going on, and possibly add the support that’s already there for physics, to the Niagara and fluid code paths, which would be a fair bit of work.

Another option is to make up collision proxies using boxes. If you can identify where the large areas are that need colliding, then you may be able to position/orient boxes to make up a rough approximation of the surface, and maybe that’s good enough. You’d be doing something like “add kDOP collision,” but manually, using the existing box primitives.

Finally, if you can do C++, you could also do the work to calculate the kDOP yourself and create the appropriate runtime object. Again, that’s a fair bit of work, but maybe less than the full “push procedural mesh support into niagara” bit.