terminalCode Example

Particle Effect system — emitters, manual emission, and custom controllers

calendar_today May 5, 2026 schedule ~1 min read person patrickjr verified 50

Particle Effect System

s&box particles are CPU-simulated and fully programmable. A particle system is built from three component types on the same GameObject: ParticleEffect (base), an emitter, and a renderer.

Minimal Setup

CSHARP
var go = Scene.CreateObject();
go.Name = "Sparks";

// 1. Base effect
var effect = go.Components.Create<ParticleEffect>();
effect.MaxParticles = 100;
effect.Lifetime     = 1.5f;  // seconds each particle lives

// 2. Emitter — burst of 20 particles
var emitter = go.Components.Create<ParticleSphereEmitter>();
emitter.Rate  = 0;    // 0 = burst only
emitter.Burst = 20;
emitter.Radius = 5f;

// 3. Renderer
var renderer = go.Components.Create<ParticleSpriteRenderer>();

Continuous Emitter

CSHARP
var emitter = go.Components.Create<ParticleSphereEmitter>();
emitter.Rate  = 30;   // 30 particles per second
emitter.Burst = 0;

Manual Emission

Emit particles one-by-one from code without an emitter component:

CSHARP
public sealed class BloodSplatter : Component
{
    ParticleEffect Effect { get; set; }

    public void Splat( Vector3 hitPoint, Vector3 normal )
    {
        for ( int i = 0; i < 8; i++ )
        {
            var p = Effect.Emit( hitPoint );
            p.Velocity = normal * Game.Random.Float( 50f, 200f )
                       + Vector3.Random * 30f;
            p.Color    = Color.Red;
            p.Size     = Game.Random.Float( 2f, 6f );
        }
    }
}

Custom Particle Controller

Implement IParticleController to fully control particle behaviour each tick:

CSHARP
public sealed class GravityController : Component, IParticleController
{
    public void Simulate( ParticleEffect effect )
    {
        foreach ( var p in effect.Particles )
        {
            p.Velocity += Vector3.Down * 200f * Time.Delta;
            p.Color     = Color.Lerp( Color.Yellow, Color.Red, p.NormalizedAge );
        }
    }
}

Pre-warming

Start the effect as if it has already been running for N seconds:

CSHARP
effect.PreWarm = 2f;  // simulate 2 seconds on first frame

Time Scale

Slow-motion or fast-forward the effect independently:

CSHARP
effect.TimeScale = 0.25f;  // quarter speed
Was this helpful?