Builtin Library
README.md
DeprecatedSimpleParticleEmitter (deprecated)
Deprecated. This belongs to the earlier particle substrate. It stays loadable by identity and guid for content that already uses it; nothing new should use it, and search does not offer it. Particles are procgen sim nodes (
sim.spawn,sim.particles,sim.shader) played through an effect: use@builtin::assetTypes.effect.
Roblox-shaped declarative particle system. Sits on top of NumberRange,
NumberSequence, and ColorSequence to describe an emitter's emission
cadence, per-particle motion, and per-particle visuals as data — no
imperative per-frame code on the user side.
The simulation and rendering run on the GPU: a compute pass integrates
every particle each frame and the whole system draws from one instanced
pass. A single emitter carries thousands of live particles at a fixed
per-frame CPU cost. The component is a thin adapter over the particles
engine module (@builtin::deprecated.deprecatedParticles.engine).
Construct
The engine registers two builtin components under the leaf name
ParticleEmitter, each with its own field vocabulary: this one, and
@builtin::deprecated.deprecatedParticles.DeprecatedParticleEmitter. Address this one by its full
identity, @builtin::deprecated.deprecatedParticles.DeprecatedSimpleParticleEmitter — the fields below are the
ones it declares.
local em = entity.spawn("flame")
em.localPosition = { 0, 1, 0 }
em.component.add("@builtin::deprecated.deprecatedParticles.DeprecatedSimpleParticleEmitter", {
rate = 50,
lifetime = NumberRange.new(1.0, 1.5),
speed = NumberRange.new(2.0, 3.0),
acceleration = { 0, 5, 0 },
color = ColorSequence.new({
{ time = 0, value = { 1, 0.9, 0.3 } },
{ time = 1, value = { 0.6, 0.1, 0 } },
}),
size = NumberSequence.new(0.4, 0.05),
transparency = NumberSequence.new(0, 1),
depthFade = 1.5,
})
depthFade is the distance, in world units, over which a particle dissolves
into the surface drawn behind it, so a plume meeting a floor settles onto it
instead of cutting a straight line along it. The default is 0, which is off.
The particles engine module's README has the whole surface.
castsShadows states whether these particles block light — a caster is drawn
into the shadow map as the geometry it is, so debris and rubble declare it while
smoke and dust leave it alone. The default is false. renderLayer names the
render layers the particles draw on, as a layer name or a space-separated
string, so a camera or a capture can take the scene with the effect in it or
without; the default is "default".
Instance methods
local em = entity.find("flame").component.get("@builtin::deprecated.deprecatedParticles.DeprecatedSimpleParticleEmitter")
em:emit(50) -- burst spawn 50, independent of rate / emitting
em:clear() -- clear every live particle right now
em.emitting = false -- stop new emission; live particles complete
Permissive input shapes
The component accepts either the strict constructed handle or the common shorthand for each sequence/range field:
| Field | Strict | Shorthand accepted |
|---|---|---|
lifetime, speed, rotation, rotSpeed | NumberRange.new(min, max) | scalar, {min, max}, {min=, max=} |
size, transparency, squash | NumberSequence.new(...) | scalar, {a, b}, {{time, value, envelope?}, ...} |
color | ColorSequence.new(...) | {r, g, b}, {r, g, b, a}, keypoint array |
acceleration, emitterSize, spreadAngle | Vector record / array | same |
Emitter shape
shape selects where particles spawn and which way each one starts
moving. It takes one of six names, in any letter case: Point, Box,
Sphere, Cylinder, Disc or Cone. Any other name is refused when
the emitter starts, with the six in the message. Box, Sphere,
Cylinder and Disc are centred on the emitter, and emitterSize gives
their extent along each axis; the table states where Point and Cone
sit.
shape | Where particles spawn | Starting direction | shapeStyle | shapePartial |
|---|---|---|---|---|
Point | The emitter's origin | Straight up (+Y) | Unused | Unused |
Box | A box emitterSize across | Volume: away from the centre. Surface: out of the face it spawned on | Volume fills it, Surface spawns on its faces | Unused |
Sphere | An ellipsoid whose diameters are emitterSize | Away from the centre | Volume fills it, Surface its shell | Above 0 keeps the upper half, flattened toward the equator; at 1 only the equator ring |
Cylinder | An upright cylinder, emitterSize.y tall, diameters emitterSize.x / .z | Out from the axis, level | Volume fills it, Surface its side wall | Shortens the band particles spawn in about the centre, to half the height at 1 |
Disc | A flat ellipse in the XZ plane, diameters emitterSize.x / .z | Out from the centre, level | Volume fills the ring between the inner radius and the rim, Surface spawns half on the rim and half on the inner edge | The inner radius as a fraction of the outer; at 0 the inner edge is the centre |
Cone | The base of a cone whose apex is the emitter's origin and whose axis is +Y, emitterSize.y above the apex | Along the line from the apex | Unused | The half-angle as a fraction of 90 degrees; 0 is a single line straight up |
shapeInOut sets the starting direction against the table's: Outward
keeps it, Inward reverses it, and InAndOut picks one of the two for
each particle. spreadAngle then tilts each direction by up to its larger
component, in degrees, so every particle leaves within that angle of the
direction the table gives it.
emissionDirection names the side of the emitter the shape's +Y faces, and
turns the whole shape there: where particles spawn and the directions they
leave in. It takes one of six names: Top (+Y, the default, which is the
table as written), Bottom (-Y), Right (+X), Left (-X), Front (-Z, the
way an entity faces) or Back (+Z). Any other name is refused with the six
in the message: a write to a running emitter keeps the side it had, and an
emitter added with one does not start. The turn is the shortest one from +Y,
so a Point emitter set to Bottom sprays straight down, a Cone set to
Front opens along -Z, and a Disc set to Right stands upright in the YZ
plane with emitterSize.z still along Z. The sides are the world's axes:
the emitter follows its entity's position, not its rotation.
local flame = entity.spawn("flame")
flame.component.add("@builtin::deprecated.deprecatedParticles.DeprecatedSimpleParticleEmitter", {
shape = "Cone",
emitterSize = { 0.6, 1.2, 0.6 },
shapePartial = 0.4,
rate = 40,
})
The emitter tracks its owning entity's world position each frame, so parenting it to a moving part sweeps the emission origin along with the part.
Demo
The campfire showcase — a warm flame emitter + slow gray smoke emitter on a log, lit by a warm point light — lives on ZeroMind as the public world "Campfire" (3d69d10d-5388-4bee-88f4-b48eb85ae222).