A downloadable tool

Get this tool and 170 more for $1,518.69 USD
View bundle
Buy Now
On Sale!
30% Off
$19.99 $13.99 USD or more

Your effect disappears when the camera pans away from it. Not faded — gone, in a single frame, while particles are still visibly on screen. It looked fine in the editor and it looks wrong in the packaged build.

That is bounds culling. A Niagara system on dynamic bounds is culled by its own bounding box, and once the box leaves the frustum the whole system stops drawing.

The engine gives you two tools for this and neither one solves it

  • A validator that checks presence, not correctness. It tells you a system has no fixed bounds. A system whose bounds are set but wrong — typed in by hand, or captured from a frame where the effect had barely started — passes clean. That is the case that actually ships.
  • A per-asset button that samples one frame. Set Fixed Bounds uses whatever is on screen the instant you press it. For anything that moves, expands or arcs, one frame is not the shape of the effect. Press it before the first particle spawns, or after a burst has died, and it does nothing at all — without saying so.

There is no batch path in the engine, and there is a structural reason for that: computing a correct bound requires simulating the system, and validation is static.

So this simulates them

For every Niagara system in your project, Niagara Bounds Solver plays it headlessly one tick at a time and takes the union of its local bounds across every tick in which a particle was actually alive. That union — the effect at its widest, not at one arbitrary instant — is what gets written as FixedBounds.

Then it writes an HTML sheet drawing the box your asset carried against the box it measured, to a shared scale, so “this one was eight times too small” is something you can see rather than something you are told.

The rule it will not break

A system it cannot honestly simulate is reported as skipped and left exactly as it was.

  • No particle alive at any sampled tick — nothing to measure, so nothing is invented.
  • Still running when the time cap is reached, such as a looping system — the union covers part of a life, not a lifetime, so it is shown and not written.
  • An instance that will not start — reported, untouched.
  • A GPU system in a run with no rendering device — named as gpu-needs-editor-run, not measured as empty.
  • A system using a stateless (Lightweight) emitter, added in UE 5.5 — named as stateless-emitter-unsupported and left alone. This version does not measure those, and it says so rather than writing a default. Mixed systems are refused too, because a union that covered only the standard emitters would be an under-bound — the very bug this removes.

That is not caution for its own sake. A wrong bound is worse than an absent one, because an absent one is at least flagged by the engine's own validator, and a wrong one validates clean and ships.

Two traps it handles that a naive version would not

  • A system that already has fixed bounds reports those bounds back at you every tick. Measuring one without forcing it back to dynamic first would “measure” the existing too-small box and confirm it as correct. The solve forces the system and its emitters to dynamic for the measurement and restores them afterwards, without dirtying the package.
  • An empty frame is not an empty box. A tick with no live particles reports a valid zero-size box, and a tick with no bounds at all gets substituted with a small default cube by the engine. Union either one in and you get a bound that is too big and centred wrong, with nothing raising an error. Every sample is gated on a live particle count instead of on the box merely looking usable.

Nothing is written until you say so, and it can be undone

Every run is a preview. -Apply is separate and deliberate. With -Apply, the previous bounds of every system about to change are written to an undo journal and flushed to disk in full before the first asset is modified — so a run that dies part way through is still reversible with -Revert. If the journal cannot be written, the run stops and nothing is applied.

What it changes, precisely

On each solved system: bFixedBounds and FixedBounds. On each GPU emitter still on dynamic bounds: CalculateBoundsMode and its FixedBounds, because the engine does not support dynamic bounds on GPU emitters and leaving one would keep the asset failing the engine's own validation. CPU emitters on dynamic are deliberately left alone. Nothing else is touched — no module, parameter, renderer, script, spawn rate, material or scalability setting.

Runs where your build runs

  • In the editorNiagaraBounds.Solve in the console, or headless with -unattended -nosplash -ExecCmds="NiagaraBounds.Solve -Apply -ExitOnFinish". This is the mode that can measure GPU systems.
  • As a commandlet-run=NiagaraBoundsSolver -Path=/Game/Effects -Apply, for a build step. GPU systems are reported as skipped here rather than silently measured as empty.

Exit codes are meaningful: an empty scan is a failure, not a pass, because a CI step that returns zero because it looked at nothing is a step that can never fail.

Honest about its limits

A simulation is not a proof. Systems are played in isolation, so an effect driven by gameplay parameters or by data interfaces that read the scene around it may occupy more space in your game than it does alone in an empty world. Randomness is sampled once, not bounded. The report states how many ticks were simulated and how many contained particles, so the basis of every number is visible — and the pad is there for the variance you expect.

What you get

  • Full C++ source, readable and commented, with the engine file and line behind every non-obvious decision.
  • Editor console command and commandlet, sharing one code path.
  • The HTML report, the undo journal and -Revert.
  • Automation tests covering the union accumulator and argument handling, including tests that pin the engine behaviours above so a later change cannot quietly undo them.

Unreal Engine 5.8, Windows. Only 5.8 is claimed, because only 5.8 was built and run.

Purchase

Get this tool and 170 more for $1,518.69 USD
View bundle
Buy Now
On Sale!
30% Off
$19.99 $13.99 USD or more

In order to download this tool you must purchase it at or above the minimum price of $13.99 USD. You will get access to the following files:

NiagaraBoundsSolver_itch_v1.0.0.zip 51 kB

Development log

Leave a comment

Log in with itch.io to leave a comment.