Quick answer: Unity particle systems default to Pause And Catch Up culling, which stops simulation when the system’s bounding box leaves the camera frustum. For gameplay-driving effects (rocket trails, projectile FX, ambient world systems), set Culling Mode to Always Simulate. If automatic culling is acceptable but the bounds are too tight, call SetCustomBounds with a volume that covers the full reach of your particles.
Here is how to fix Unity particle systems that stop when off screen. You build a beautiful smoke trail behind a missile, you fire it past the camera, and the moment the camera turns away the trail freezes mid-air. You turn the camera back, and the trail teleports forward as if catching up — or worse, the smoke is just gone, replaced with a wall of fresh particles all spawned in the same instant. Unity is doing exactly what its default settings tell it to do: save CPU when nobody is looking. For pure decoration this is fine; for anything gameplay-relevant it is a bug.
The Symptom
The particle pause manifests differently depending on how aggressive the culling is and what the system was emitting:
Smoke trail snaps forward. You watch a projectile leave the screen, look back a second later, and the trail is bunched up at the projectile’s current position with a discontinuity where the off-screen frames should have been. The simulation paused; the projectile kept moving; the gap between the last visible particle and the next one is huge.
Burst on return to view. You look away for several seconds. When you look back, the particle system spawns a wall of particles in a single frame — the entire backlog of emissions that should have happened during the off-screen interval, all coming through at once. This is the Catch Up behaviour.
Effect appears stopped permanently. The particle system never resumes even after the camera frames it again. This usually means the bounding box used for culling has not been updated since the camera moved, so the system thinks it is still off-screen and stays paused.
One-shot effect skipped entirely. A short-lived burst (e.g., a muzzle flash) emitted during the off-screen interval gets skipped, then catches up to find the lifetime is already over and shows nothing. The effect appears to never have happened.
What Causes This
Culling Mode default. The Renderer module of every particle system has a Culling Mode field. The default is Automatic, which Unity translates to Pause And Catch Up for systems with predictable motion and Always Simulate for systems with sub-emitters or random forces. This heuristic is conservative and often picks Pause when you wanted Always Simulate.
Bounding box too small. The particle system computes its own bounds from recent particle positions. If your particles travel a long distance from the emitter (a rocket trail, a thrown grenade), the bounding box may not yet have grown to cover the full reach when the camera looks away. The box leaves the frustum, the system pauses, and the bounds never get a chance to grow.
Sub-emitters and inheritance. A sub-emitter that spawns from a parent particle inherits the parent’s culling state. If the parent is paused, the child never spawns. This bites you when a hit effect spawns secondary debris — the debris does not appear because the hit effect was off-screen.
Time.timeScale interaction. When Time.timeScale is zero (e.g., during a pause menu) particle systems do not tick. If your culling mode resumes the system mid-pause, the catch-up step uses the wall-clock delta but the simulation step uses scaled time, leading to inconsistent results.
The Fix
Step 1: Identify systems that need to be authoritative. Walk your project and tag every particle system that drives gameplay or that needs to look correct regardless of camera position. Common candidates: projectile trails, persistent ambient systems (rain, snow, dust), one-shot bursts that the player might not be looking at, and any system that triggers audio or gameplay events from sub-emitters.
Step 2: Set Culling Mode to Always Simulate. For each tagged system, open the Renderer module, find Culling Mode, and change it from Automatic to Always Simulate. The system will tick every frame regardless of camera state. This costs CPU but produces correct behaviour.
using UnityEngine;
public class ParticleCullingSetup : MonoBehaviour
{
[SerializeField] private ParticleSystem trailSystem;
private void Awake()
{
// Force the system to tick regardless of camera position.
// Costs CPU; necessary for any gameplay-driving effect.
ParticleSystem.MainModule main = trailSystem.main;
main.cullingMode = ParticleSystemCullingMode.AlwaysSimulate;
// Optional: also expand bounds so even if culling were on,
// the bounding box would cover the full reach of the trail.
Bounds wideBounds = new Bounds(
center: Vector3.zero,
size: new Vector3(50f, 20f, 50f));
trailSystem.SetCustomBounds(wideBounds);
}
}
Step 3: For decorative systems, just expand the bounds. Keep automatic culling but give the system a custom bounding box that covers the full extent of where particles can travel. The system still pauses when the entire box leaves the frustum, but the box now needs to leave the frustum entirely — which is much harder.
Step 4: Profile the cost. Always Simulate is more expensive than the default. Open the Profiler, switch to the CPU module, and inspect the ParticleSystem.Update sample with and without your changes. If the cost spike is unacceptable, restrict Always Simulate to the systems that genuinely need it and accept automatic culling for pure decoration.
Detecting Off-Screen Skipped Effects
For one-shot effects you definitely want the player to see if they look back, you can self-pause the system on emission and only resume it once a camera is actually framing the location. This is more work but it lets you stage effects deterministically:
using UnityEngine;
[RequireComponent(typeof(ParticleSystem))]
public class StagedHitEffect : MonoBehaviour
{
private ParticleSystem ps;
private Camera mainCam;
private bool hasPlayed;
private void Awake()
{
ps = GetComponent<ParticleSystem>();
mainCam = Camera.main;
ps.Stop();
}
private void Update()
{
if (hasPlayed) return;
// Stage emission until the camera can actually see this point.
Vector3 viewport = mainCam.WorldToViewportPoint(transform.position);
bool visible = viewport.z > 0f
&& viewport.x > 0f && viewport.x < 1f
&& viewport.y > 0f && viewport.y < 1f;
if (visible)
{
ps.Play();
hasPlayed = true;
}
}
}
This pattern is overkill for trails but useful for staged narrative effects — an explosion you scripted to happen at a specific moment, where the player turning their head should not skip the moment. Combine with a maximum staging duration so the effect does not wait forever if the player never looks.
Sub-Emitter Quirks
Sub-emitters inherit culling from their parent. If a parent system is paused, a sub-emitter cannot spawn even if you would otherwise expect it to. For sub-emitter chains where the child needs to play even when the parent is off-screen, set cullingMode = AlwaysSimulate on both the parent and the child explicitly. Setting it only on the child does nothing because the parent never reaches the spawn step.
“Automatic culling is a performance default that assumes nobody cares about invisible particles. The day you start using particles for gameplay, that assumption breaks.”
Related Issues
If your particle system never plays at all (visible or not), see Particle System Not Playing. For lit particles flickering during alpha-blended overdraw, check Particle System Lit Shader Flickering.
Tag your gameplay-relevant FX, set them to Always Simulate, and let the rest cull — balance correctness and CPU on a per-system basis.