Skip to content

Particles

ParticleEmitter controls an emitter placed in a scene; Particles.Spawn fires an effect at a point with no entity to place first. For authoring the effects themselves, see the Particle effects guide.

ParticleEmitter

csharp
public class Torch : GameEntity
{
    private ParticleEmitter? m_Flame;

    protected override void OnCreate()
    {
        m_Flame = GetComponent<ParticleEmitter>();
    }

    public void Extinguish() => m_Flame?.Stop();
    public void Relight()    => m_Flame?.Play();
}

Every call forwards to the entity's particle pool, which is created lazily on the entity's first scene update. Calling any of these before that, or on an entity with no effect assigned, is a harmless no-op.

Play()

Starts, or resumes, emitting.

Pause()

Freezes the effect exactly where it is.

Stop(bool clear = false)

Stops emitting. By default the particles already alive finish their lifetimes naturally — almost always what you want when a torch is extinguished or a thruster cuts out.

csharp
m_Flame.Stop();              // stop emitting, let the flame die down
m_Flame.Stop(clear: true);   // instant cut — for a scene transition

Restart()

Back to the beginning of the effect's cycle.

Emit(int count)

Releases particles immediately, ignoring the emission rate. This is the one-shot every gameplay event wants — a hit spark, a footstep puff.

csharp
protected override void OnCollisionEnter(Collision2D collision)
{
    m_Sparks?.Emit(12);
}

EmitDirected(int count, Vector2 direction, float spreadDegrees = 0.0f)

The same one-shot, but aimed — regardless of the shape the effect was authored with. For a bullet hitting a wall at an angle, or blood spraying away from an impact.

csharp
m_Impact?.EmitDirected(20, hitNormal, spreadDegrees: 30f);

IsPlaying

Whether the emitter is currently emitting.

AliveCount

How many particles exist right now. Useful for waiting until an effect has finished before despawning its entity.

csharp
private System.Collections.IEnumerator DespawnWhenDone()
{
    m_Emitter!.Stop();
    while (m_Emitter.AliveCount > 0)
        yield return null;
    m_Pool.Release(this);
}

EmissionRate

Particles per second. Read and write — so an engine exhaust can scale with throttle.

csharp
m_Exhaust.EmissionRate = 10 + m_Throttle * 80;

TintMultiplier

A Vector4 multiplied into the whole effect's colour. Read and write. This is how one explosion asset becomes a red one and a blue one without authoring two files.

csharp
m_Explosion.TintMultiplier = new Vector4(0.4f, 0.6f, 1.0f, 1.0f);   // blue variant

Particles

Particles.Spawn(string particleAssetPath, Vector3 position)

Particles.Spawn(string particleAssetPath, Vector3 position, float rotation)

Spawns a one-off effect at a world position. The engine owns the entity it creates and destroys it once the effect finishes, so there is nothing to clean up.

csharp
Particles.Spawn("Effects/Explosion.jparticle", Translation);
Particles.Spawn("Effects/Impact.jparticle", hitPoint, rotation: angle);

Returns the spawned entity if you need it, or null if it couldn't be spawned.

Looping effects are refused

Spawn destroys the entity when the effect finishes — and a looping effect never finishes, so passing one returns null rather than leaking an entity that lives forever. Use a placed emitter for anything that loops.

The refusal is quiet: check the return value if you're not certain what a designer put in that asset.

Which one to use

Use a placed emitterUse Particles.Spawn
Looping effect (fire, smoke, waterfall)❌ refused
Attached to a moving entity
Needs runtime control (rate, tint, pause)
A burst at a point that just happenedPossible, but clutters the scene

See also