Working with Particle Systems
Make explosions, sparks, smoke, dust and rain, and control them from your scripts.
A Particle System is a confetti cannon with a lot of dials. One dial sets how many pieces fly out, another sets which direction, another how long each piece lasts, another what colour it fades to. Each piece of confetti (a particle) is just a tiny picture that always faces the camera.
Make your first effect
- GameObject > Effects > Particle System. White dots start floating upward.
- With it selected, a small Particle Effect panel appears in the Scene view with Play, Restart and Stop buttons, so you can preview without entering Play mode.
- In the Inspector, the settings are split into modules. Click a module's name to open it and tick its box to turn it on.
The modules you'll use most
| Module | Controls | Key settings |
|---|---|---|
| Main (top section) | Each particle's starting look | Duration, Looping, Start Lifetime, Start Speed, Start Size, Start Color, Gravity Modifier, Simulation Space |
| Emission | How many come out | Rate over Time (steady stream) or Bursts (all at once) |
| Shape | Where they come from and which way they go | Cone, Sphere, Box, Circle, Edge, Mesh |
| Color over Lifetime | Colour and fade as they age | A gradient: set alpha to 0 at the end to fade out |
| Size over Lifetime | Grow or shrink as they age | A curve from 1 down to 0 looks like sparks burning out |
| Noise | Wobbly, natural movement | Strength, Frequency |
| Collision | Bounce off the world | Type: World, Bounce, Lifetime Loss |
| Renderer | What each particle looks like | Material, Render Mode (Billboard, Stretched, Mesh) |
Tip: many values have a small ▼ next to them. Choose Random Between Two Constants to add variety, e.g. Start Size 0.1 to 0.3. Variety is what makes effects look natural.
Recipes
Explosion burst
- Main: Duration 1, Looping off, Start Lifetime 0.4–0.8, Start Speed 5–10, Start Size 0.2–0.5.
- Emission: Rate over Time 0. Add a Burst: Time 0, Count 40.
- Shape: Sphere.
- Color over Lifetime: yellow → orange → transparent. Size over Lifetime: shrink to 0.
Dust puffs behind a running character
- Main: Looping on, Start Speed 0.5, Simulation Space: World (so puffs stay behind instead of following you).
- Emission: Rate over Time 0, Rate over Distance 3. Now it only puffs while moving.
- Color over Lifetime: fade from light brown to transparent.
Rain
- Shape: Box, wide and flat, placed above the camera. Rotate it so particles go down.
- Main: Start Speed 15, Max Particles 2000. Emission: 500 per second.
- Renderer: Stretched Billboard with Speed Scale 0.05 to turn dots into streaks.
Local vs World simulation space
Controlling particles from code
using UnityEngine;
public class ParticleExamples : MonoBehaviour
{
[SerializeField] private ParticleSystem sparks;
void Examples()
{
sparks.Play(); // start emitting
sparks.Stop(); // stop emitting; existing particles finish their life
sparks.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear); // vanish now
sparks.Emit(20); // spit out 20 particles immediately, even if stopped
bool busy = sparks.IsAlive(); // true while any particle is still visible
}
}
Changing settings: the module gotcha
Modules must be copied into a local variable first. You can't set them in one line:
// ❌ Won't compile
sparks.main.startColor = Color.red;
// ✅ Grab the module, then change it. It still updates the real system.
var main = sparks.main;
main.startColor = Color.red;
main.startSpeed = 8f;
var emission = sparks.emission;
emission.rateOverTime = 50f;
The variable is a handle to the particle system, not a copy of the data. Changing it changes the real effect.
Example: play a hit effect where a bullet lands
using UnityEngine;
public class HitEffect : MonoBehaviour
{
[SerializeField] private ParticleSystem hitPrefab;
void OnCollisionEnter(Collision collision)
{
ContactPoint contact = collision.GetContact(0);
// Face the effect away from the surface that was hit
Quaternion rotation = Quaternion.LookRotation(contact.normal);
Instantiate(hitPrefab, contact.point, rotation); // a cone shape sprays along the blue Z arrow
// On the prefab: Looping off, Stop Action = Destroy, so it cleans itself up
}
}
The Stop Action (in the Main module) decides what happens when the effect finishes: Destroy removes the GameObject, Disable switches it off, Callback calls OnParticleSystemStopped() on your script. If effects spawn often, pool them using Disable or Callback instead of Destroy.
Sub Emitters: effects inside effects
The Sub Emitters module starts a second particle system when a particle is born, dies or collides. Classic use: a firework rocket particle that triggers a burst explosion when it dies.
Materials in URP
Particles need a particle material. In URP, create a material with Universal Render Pipeline/Particles/Unlit (or Lit if it should react to lights), set Surface Type to Transparent, and give it a soft round texture. Then drag it into the Renderer module's Material slot. Pink particles mean the material isn't a URP one.
Keep it fast
- Max Particles (Main module) is a safety cap. Keep it close to what you need.
- Big see-through particles covering the screen are the #1 cost (called overdraw). Use fewer, smaller particles.
- Collision set to World is expensive. Use Planes or low quality if you only need a floor.
- For millions of GPU particles, look at VFX Graph (a separate package, better on PC and console).
Common Mistakes
- Leaving Looping on for a one-shot explosion, so it never ends and never gets destroyed.
- Leaving Play On Awake on for an effect you meant to trigger from code.
- Trying
ps.main.startSize = 2in one line. Copy the module to a variable first. - Moving character dust in Local space, so the "trail" sticks to the character's feet.
- Instantiating and destroying a new effect for every bullet hit in a busy game. Pool them.
See also
- Object Pooling (has a pooled particle example)
- URP & Post-processing (Bloom makes sparks glow)
- Camera-facing Billboards
This page is a simplified, AI-assisted interpretation. For the complete and authoritative reference, see the official documentation.