Guides VFX & Particles Particles Create a 3D Particle Effect

VFX & Particles Particles 3 min read Updated Aug 2026

Create a 3D Particle Effect

This guide creates a 3D particle emitter for effects such as sparks in a 3D scene, smoke near a torch, falling rain, magic glints around an object, or debris from an impact.

Create The Emitter

  1. Select or create the GameObject that should own the effect.
  2. In the Inspector, choose Add Component.
  3. Open 3D.
  4. Open Rendering.
  5. Choose Particle System.

Set Dimension to 3D if it is not already selected. The 3D template uses 3D shape data and billboard rendering by default.

Place the GameObject where particles should spawn. For scene effects, a child GameObject is often useful: parent it to the object that owns the effect, then offset the particle child to the exact source point.

Pick A Shape

3D particles can spawn from several emitter shapes:

  • Point: all particles start at the emitter origin
  • Sphere: particles spawn throughout or around a sphere
  • Hemisphere: useful for upward sprays, domes, and environmental effects
  • Box: useful for rain, snow, fog volumes, and rectangular zones
  • Cone3D: useful for sparks, smoke jets, muzzle flashes, and directional sprays

For a torch smoke effect, use Cone3D with a narrow spread and low speed. For rain, use Box with a large horizontal size and downward velocity/force. For magic motes around an object, use Sphere with low speed and looping enabled.

Use Billboards

Most 3D particles render as billboards: flat quads that face the camera. Billboards are cheap and read well for smoke, sparks, dust, embers, and magic effects.

Renderer modes include:

  • Billboard: faces the active camera
  • StretchedBillboard: stretches along motion for fast streaks
  • HorizontalBillboard: lies horizontally, useful for ground rings or flat splashes
  • VerticalBillboard: stays upright, useful for stylized effects
  • Mesh: mesh-shaped particles when the effect uses an assigned mesh

If a 3D particle texture looks like a flat card, that is expected. The trick is to use soft texture edges, additive or alpha blending, and enough particle variation that the cards read as a volume.

Tune Space And Motion

Simulation Space decides whether particles follow their emitter after spawning.

Use Local when particles should move with the object that emitted them. This is useful for engine glows, magic auras, and attached effects.

Use World when particles should remain in world space after spawning. This is useful for smoke, dust, rain, and debris. If a torch moves, smoke usually should not snap along with it.

Start Speed, Force Over Lifetime, and Velocity Over Lifetime shape the motion. A smoke effect often uses low speed and upward force. Sparks use higher speed and may use gravity-like downward force.

Keep The Camera In Mind

3D particle effects depend on camera distance and field of view. A particle size that reads well near the camera may disappear at distance, while a size that reads from far away can look enormous up close.

When tuning a 3D effect:

  • test from gameplay camera distance
  • test while moving the camera
  • check whether billboards clip into nearby geometry
  • avoid relying on tiny particles for important gameplay feedback
  • keep dense volumetric effects bounded so they are cheap to cull

Preview The Effect

Select the emitter and enable the scene view FX toggle. The preview will simulate the selected particle system using its 3D dimension and transform data.

If nothing appears:

  • confirm the system is 3D
  • use Billboard renderer mode first
  • increase Start Size
  • increase Rate over Time
  • verify the effect is inside the scene view camera frustum
  • check that the texture path is valid

Trigger From PHP

use Lenga\Engine\Core\Behaviour;
use Lenga\Engine\Core\ParticleSystem;

final class ImpactSparks3D extends Behaviour
{
    private ?ParticleSystem $sparks = null;

    public function start(): void
    {
        $this->sparks = $this->getComponent(ParticleSystem::class);
        $this->sparks?->dimension = '3D';
        $this->sparks?->stop(true);
    }

    public function playImpact(): void
    {
        $this->sparks?->restart(true);
        $this->sparks?->emit(40);
    }
}

For reusable effects, prefer loading a .particle.json profile instead of setting many values from PHP.