Quick answer: Query particle count via the SystemInstanceController per emitter, after the tick. CPU emitters return live counts; GPU emitters lag by a few frames due to async readback.

You want to gate gameplay on “all spawned particles done.” GetActiveParticleCount returns 0 even though particles visibly exist.

The Symptom

API call from C++ returns wrong count. Visual count obvious in the Niagara overlay debugger.

The Fix

UNiagaraComponent* Comp = ...;
TSharedPtr<FNiagaraSystemInstanceController> Ctrl = Comp->GetSystemInstanceController();
if (Ctrl.IsValid())
{
    int32 Total = 0;
    for (int32 i = 0; i < Comp->GetAsset()->GetEmitterHandles().Num(); ++i)
    {
        FNiagaraEmitterInstance* Em = Ctrl->GetSimulationForHandle(i).Get();
        if (Em) Total += Em->GetParticleCount();
    }
    UE_LOG(LogTemp, Log, TEXT("Active: %d"), Total);
}

Loop through emitters, sum counts. Call from PostUpdate or after manual Tick to ensure data is fresh.

GPU Emitters

GPU counts use async readback. Expect 1–3 frames of latency. For gating on “completely done,” wait until count is 0 for several consecutive frames.

Verifying

Spawn a known number of particles via Burst Spawn = N. Wait one tick. Query count; should return N. Subsequent frames decrease as particles expire.

“Per-emitter count after tick. GPU has lag. Sum gives total.”

Related Issues

For Niagara CPU/GPU readback, see CPU/GPU readback. For Niagara mesh attribute, see mesh attribute.

Per-emitter, after tick. Counts arrive.