Skip to content

ParticleEmitter

ParticleEmitter manages a Tier 2 (Jolt physics) particle system. Each particle is a Jolt dynamic body that collides with the world. Particles are rendered via InstancedMesh internally. Create via Scene.createParticleEmitter.

An emitter can also render its particles as non-physics sprites — surface-pinned rings and camera-facing sparkles that back water splashes and ripples. See Sprite render modes.

scene.createParticleEmitter(name, maxBodies, size, mass, lifetime, emissionRate, x, y, z)

Section titled “scene.createParticleEmitter(name, maxBodies, size, mass, lifetime, emissionRate, x, y, z)”

Returns: ParticleEmitter — A new emitter registered with the scene.

Parameters:

  • name (String) — Identifier for this emitter.
  • maxBodies (Num) — Maximum particle pool size (number of simultaneous physics bodies).
  • size (Num) — Particle size in metres.
  • mass (Num) — Particle mass in kg.
  • lifetime (Num) — Particle lifetime in seconds.
  • emissionRate (Num) — Particles emitted per second.
  • x, y, z (Num) — Initial emitter position.
_emitter = _scene.createParticleEmitter("sparks", 128, 0.05, 0.1, 2.0, 50, 0, 3, 0)

Emitters can also be loaded automatically from .blend particle systems when instantiating with Resource.loadBlend.

MethodDescription
play()Start emitting particles continuously at emissionRate.
stop()Stop emitting new particles (existing ones continue until their lifetime expires).
pause()Pause all simulation (freeze existing particles in place).
resume()Resume from a paused state.
burst(count)Immediately spawn count particles at the emitter position, ignoring emission rate.
_emitter.play()
// On explosion:
_emitter.burst(64)
PropertyReturnsDescription
isPlayingBooltrue if emitting (not stopped or paused)
isPausedBooltrue if paused
activeCountNumCurrent live particle count
maxBodiesNumMaximum pool size (set at creation)
nameStringEmitter name
emissionRate=(rate)—Set particles per second

Move the emitter origin. New particles spawn from this position.

Set the emission direction normal. Particles are given initial velocity along this direction (plus any random/tangential factors configured in the blend).

// Follow a node
var pos = _nozzleNode.getWorldPosition()
_emitter.setPosition(pos[0], pos[1], pos[2])
var fwd = _nozzleNode.getForward()
_emitter.setNormal(fwd[0], fwd[1], fwd[2])

Use the mesh from a Node to render particles instead of the default sphere.

_emitter.setMeshFromNode(_sparkMeshNode)

(engine main, ADR 0102)

An emitter can render its particles as non-physics sprites instead of physics-body meshes — the render path that backs water splashes and ripples. The sprite modes reuse the existing sprite pipeline, so there is no Vulkan renderer change. A sprite particle is a pinned kinematic decal: it has no Jolt body, stays where it spawns, and animates only via a scale-over-life and an alpha-over-life curve.

Select how the emitter’s particles are drawn:

modeNameWhat it is
0PhysicsMesh(default) Jolt dynamic body + instanced mesh — the Tier 2 physics particles described above. Splash spray stays this mode.
1SpriteGroundA soft sprite laid flat on the world XZ plane (BillboardMode::Ground). Burst one per beat for concentric, expanding, fading rings — a raindrop / footfall / floating object hitting water.
2SpriteBillboardThe same sprite, camera-facing — e.g. a twinkling sparkle above the surface.

World-unit sprite half-size from spawn to death. Growing it (e.g. 0.25 → 3.2) turns a point into a wide ring.

Sprite opacity from spawn to death (e.g. 0.9 → 0.0 fades out over the particle’s life).

Sprite RGB tint, each channel in [0, 1]. Alpha comes from the alpha curve, not from this call.

The sprite texture — typically a soft ring — a Texture obtained from Texture.load(path).

// A surface-pinned ripple ring: flat on the water, grows + fades.
// Args: name, maxBodies, size, mass, lifetime, emissionRate, x, y, z
_ripples = _scene.createParticleEmitter("ripples", 64, 0.1, 0.0, 1.8, 0.0, 0, 0.02, 0)
_ripples.setRenderMode(1) // SpriteGround — flat on the XZ plane
_ripples.setTexture(Texture.load("textures/ring.png"))
_ripples.setScaleCurve(0.25, 3.2) // half-size: spawn → death
_ripples.setAlphaCurve(0.9, 0.0) // fade out
_ripples.setColor(0.72, 0.90, 1.0) // pale cyan
_ripples.play()
// Each beat, pin a fresh ring at the impact point:
_ripples.setPosition(x, 0.02, z)
_ripples.burst(1)

Sprite particles are submitted through the sprite pipeline when the scene is drawn (Scene.draw()). See the Particle FX Demo example.


See InstancedMesh for non-physics GPU instancing. See Scene for createParticleEmitter. See Physics for body configuration details (collision layers in game.toml apply to particle bodies).