Niagara ribbon renderer + beam bounds issue


I’m creating a bullet trail effect where the niagara system is created at the gun’s fire point, and it renders a beam (‘Beam Emitter Setup’, ‘Spawn Beam’, ‘Update Beam’) using Ribbon Renderer, to the bullet impact point.

The problem: if occlusion culling is enabled in project settings, the system is culled and destroyed after the first frame. This happens because dynamic bounds are incorrectly calculated. If you look at niagara sources, you’ll find that the only thing that affects dynamic bounds for ribbon renderer is ribbon width parameter, which is more or less useless when rendering beams. One would assume that setting fixed bounds could solve the issue, but you can’t use fixed bounds with CPU simulations (and GPU sims are not available for ribbon renderer).

So the question is - what’s the intended way of rendering beams using niagara? Ribbon renderer looks like the way to go, except the culling issue.

If that’s an oversight, what the proper solution would look like? Enable fixed bounds to be used with ribbon renderer, or somehow access beam settings (start and end points) in dynamic bounds calculator and properly expand the bounds?

Alternatively, is there a way to somehow manually modify/expand dynamic bounds from script (either C++ or blueprint)?

EDIT: Disregard most of the above - since beam width sets ribbon width parameter, I was able to expand the bounds (even though it caused visual problems) and the system/emitter was still culled. Looks like it’s not the bounds issue. I’ve also tried setting scalability of the emitter to ‘self’ and make sure that ‘enable visibility culling’ is disabled, which didn’t help either. Now I’m completely lost and have no idea how to disable culling for this particular system without globally disabling occlusion culling.


After even more debugging, I’ve found that spawning the system with any owner actor other than the default (which is World->GetWorldSettings()) does fix the culling problem.

So my workaround was to create a custom version of UNiagaraFunctionLibrary::SpawnSystemAtLocation() which accepts an additional AActor* OwnerActor param and uses it instead of World->GetWorldSettings(). It’s exposed to blueprints and I use it where I would otherwise use the base SpawnSystemAtLocation function.