Quick answer: Use part_particles_create for one-shot bursts — no emitter needed. If you need positional/region control, use part_emitter_burst and destroy the emitter after.
You wanted a brief puff of sparks when the player jumps. You wrote part_emitter_stream in the jump event. The first jump produces the puff, then the puff continues for the rest of the game. The emitter is streaming because that’s its job; you asked for streaming.
The Two Spawn Functions
GameMaker offers two emission modes on the same emitter:
- part_emitter_burst(ps, em, ptype, count) — emit
countparticles immediately, once. The emitter remains in the system for future bursts. - part_emitter_stream(ps, em, ptype, per_step) — emit
per_stepparticles every game step until you callpart_emitter_stream(ps, em, ptype, 0)to stop.
If you accidentally call stream when you meant burst, particles flow forever.
Simple Fix for One-Shot Effects
For a positional burst at a single point, skip the emitter entirely:
/// obj_player Jump event
part_particles_create(global.ps, x, y + 16, pt_dust, 12);
part_particles_create spawns count particles of type pt_dust at the given coordinates. No emitter management. Each call is a one-shot burst.
When You Need a Region Burst
For an explosion that covers an area:
/// On explosion trigger
var em = part_emitter_create(global.ps);
part_emitter_region(global.ps, em, x - 32, x + 32, y - 32, y + 32, ps_shape_ellipse, ps_distr_gaussian);
part_emitter_burst(global.ps, em, pt_fire, 80);
part_emitter_destroy(global.ps, em);
Create emitter, set region, burst, destroy. Doing this each time avoids leaked emitter handles.
For Repeated Bursts
If you need bursts at the same emitter region repeatedly (e.g., a periodically erupting volcano), keep the emitter alive and only burst:
/// Create
em = part_emitter_create(global.ps);
part_emitter_region(global.ps, em, x - 16, x + 16, y, y, ps_shape_line, ps_distr_linear);
/// Alarm 0 (every 2 seconds)
part_emitter_burst(global.ps, em, pt_lava, 40);
alarm_set(0, 120);
/// Clean Up
part_emitter_destroy(global.ps, em);
Emitter persists across alarm cycles; each burst emits a fresh wave; destroy when the instance is gone prevents leaks.
Diagnosing Existing Code
If you have an unexplained continuous particle stream, search for part_emitter_stream in your project:
grep -rn part_emitter_stream scripts/ objects/
For each match, decide: should it be part_emitter_burst? Or should it be stream with an explicit stop call later? Streams without stop calls keep emitting forever.
Verifying
Trigger the effect and watch the particle system’s active particle count via part_particles_count(global.ps). Print it each step. The count should rise momentarily then fall back to 0 (or the previous level). If it climbs and stays high, particles are still being emitted continuously.
“Burst for one-shot, stream for continuous. Confusing them produces effects that won’t stop or won’t start.”
For impact effects, part_particles_create is shorter, simpler, and leak-free. Prefer it over emitter-burst-destroy.