Quick answer: Call ps.Stop(true, ParticleSystemStopBehavior.StopEmitting) so existing particles can finish, then Destroy after IsAlive(true) goes false. Or set Stop Action = Destroy in the inspector.
A one-shot explosion is destroyed immediately after spawning — players see no particles. Destroying the system kills its alive particles instantly.
Stop Emitting, Let Them Age Out
ps.Stop(true, ParticleSystemStopBehavior.StopEmitting);
IEnumerator DestroyWhenDone()
{
while (ps.IsAlive(true)) yield return null;
Destroy(gameObject);
}
StartCoroutine(DestroyWhenDone());
StopEmitting halts new particle spawns but lets existing ones live out their lifetime. IsAlive(true) returns true while any sub-emitter still has particles.
Or Stop Action in the Inspector
Main module → Stop Action = Destroy (or Disable / Callback). Once the system stops and no particles remain, Unity destroys the GameObject for you — no coroutine needed.
Pooling Alternative
For frequent effects, pool the system instead of destroying. Disable when done, re-enable and Play on next use — no allocations, no destroy timing concerns.
Verifying
Explosions play to completion. The GameObject goes away after the last particle dies. No effects cut off mid-burst.
“Stop emitting, wait for IsAlive, then destroy. Or let Stop Action = Destroy do it.”
For looping effects (smoke), you also need to actually call Stop — just destroying mid-loop cuts particles dead too.