s&box
RustCounter-Strike 2s&boxDeadlock
Wiki
Get s&box on Steam
Browse
OverviewGetting StartedCreating GamesEngine & ToolsDocumentationCommunity GamesResources
s&boxDocumentationRenderingEffectsParticle EffectCustom Particle Controller
SOURCE 2 · C#
Build and play games with s&box.

Facepunch's game engine and creation platform — make games in C#, or jump straight into community games.

Get s&box on Steam

s&box Wiki

  • Overview
  • Getting Started
  • Creating Games
  • Engine & Tools
  • Documentation
  • Community Games
  • Resources

Tools & Community

  • Getting Started
  • Creating Games
  • Engine & Tools
  • Resources

Platforms

  • RustBattle
  • CSBattle
  • Rust Game Wiki
  • CS2 Skins Wiki
  • Deadlock Wiki

About

  • Official Site
  • Developer Wiki
  • GitHub
  • Get on Steam
NOT AFFILIATED WITH FACEPUNCH STUDIOS · © 2026 s&box Wiki (community)
Docs/Rendering
Rendering

Custom Particle Controller

The particle system is designed to let you control the particles via your own code based components, if you choose to.

To do this, just inherit a component from ParticleController.

public class MyParticleController : ParticleController
{
	protected override void OnParticleStep( Particle particle, float delta )
	{
        // apply gravity
		particle.Velocity += Vector3.Down * 900 * delta;
	}
}

Then add this to your GameObject with a Particle Effect on it. You will see that the particles go up, slowly.

This method is called for each particle in the particle system. The second argument is the time delta (which is the game time delta multiplied by the particle system's time delta).

This method is run in a thread, so you should be careful about what you're doing here. For example, don't create callbacks here, don't delete GameObjects or components etc.

For convenience, there are functions that are called before and after the particle step. These are always called on the main thread, so you can execute any callbacks you need to here. Here's an example.

public class MyParticleController : ParticleController
{
	Action callbacks;

	protected override void OnBeforeStep( float delta )
	{
		callbacks = null;
	}

	protected override void OnParticleStep( Particle particle, float delta )
	{
		if ( particle.Age > 10.0f )
		{
			lock ( this )
			{
				callbacks += () => SceneUtility.Instantiate( myPrefab, particle.Position );
			}
		}
	}

	protected override void OnAfterStep( float delta )
	{
		callbacks?.Invoke();
		callbacks = null;
	}
}

Source: Facepunch/sbox-docs (CC-BY-4.0) · updated 2023-11-27. Read it rendered on the official docs.

More in Rendering

AmbientLight
Animated Effects
Attributes and Variables
BeamEffect
Beams
Bindless API
C# Shader Nodes
Classes
← All documentation

Community wiki — not affiliated with Facepunch Studios. For the latest and most authoritative information, see the official developer wiki.