effects
The effects namespace — 31 functions.
globals/effects/backends
effects.backends() -> { string }
The backend kinds an effect can be built out of, in name order. The
runtime ships emitter, geometry, material, decal and feature.
Returns { string } — Array of kind names.
print(table.concat(effects.backends(), ", "))
globals/effects/describe
effects.describe(identity: string) -> { [string]: any }
What an effect declares about itself: its family, a one-line summary, every parameter with its type, default and documented range, and the cost one unpooled play of it was measured to draw. The one call to make against an unfamiliar effect before playing it.
Parameters
identitystring— The effect's canonical identity, or a short name.
Returns { [string]: any } — { identity, family, summary, cost, params }.
local d = effects.describe("explosion"); print(d.family, d.cost.gpuMs)
globals/effects/drain
effects.drain() -> { [string]: number }
Free every backend the pool is holding idle. The pool keeps what it has leased for as long as the engine runs — that is what makes repeated firing cost nothing after the first — and this is the one call that gives it back. A backend a live play still holds is left to that play's own end.
Returns { [string]: number } — { freed, kept }.
print(effects.drain().freed)
globals/effects/families
effects.families() -> { string }
Every family the effects in this world declare, sorted — the values
list { family = … } filters on. An effect declaring no family is not one
of them.
Returns { string } — Array of family names.
for _, f in ipairs(effects.families()) do print(f, #effects.list({ family = f })) end
globals/effects/list
effects.list(opts: table?) -> { string }
The canonical identity of every effect this world can play, sorted.
These are the exact strings play takes. Pass { family = "combat" } to
get only the effects of one family — the catalogue filtered the way an
effect declares itself.
Parameters
optstable(optional) —{ family? = string }. A family is matched without regard to case.
Returns { string } — Array of identities.
for _, id in ipairs(effects.list()) do print(id) end
for _, id in ipairs(effects.list({ family = "combat" })) do print(id) end
globals/effects/observe
effects.observe() -> { [string]: any }
What the runtime is holding and driving right now — every live play with
the reason it is silent when it is, plus what the pool has leased out and
what it is keeping idle, in instances and in GPU bytes. This is how a caller
and a test tell a working effect from a silent one, and how they tell a pool
warming to a wider burst from something leaking: the pool is sized by the
most effects it has had to cover at once, which peakLive and peakLeased
report beside the current totals.
Returns { [string]: any } — The observation.
local o = effects.observe(); print(o.live, o.leased, o.pooled, o.bytes)
print(o.peakLive, o.peakLeased) -- the widest burst the pool covers
globals/effects/play
effects.play(identity: string, opts: table?) -> any
Play an effect once at a world position. The effect allocates what it needs from the shared pool, draws itself, and gives everything back when it ends — with no update loop on the caller's side.
Parameters
identitystring— The effect's canonical identity, or a short name that reaches exactly one effect.optstable(optional) —{ position? = { x, y, z }, rotation? = quat, direction? = { x, y, z }, params? = { … }, duration? = number, held? = boolean }. Anythingparamsomits takes the effect's declared default, and an effect that declares adurationparameter reads its length from there rather than fromdurationhere.
Returns any — The play handle — stop, cancel, retarget, setParam, isPlaying, isFinished, seek, stats, whySilent.
local h = effects.play("@builtin::systems.effects.combat.explosion", {
position = { 0, 2, 0 }, params = { scale = 4, coreColor = { 1, 0.4, 0.1 } },
})
globals/effects/playOn
effects.playOn(identity: string, target: any?, opts: table?) -> any
Play an effect on an entity: it starts where the entity stands and ends
if the entity leaves the world. Move it with the entity by calling
handle:retarget(theEntity) as it goes.
Parameters
identitystring— The effect's canonical identity, or a short name.targetany(optional) — An entity proxy or entity id.optstable(optional) — The same optionsplaytakes;positionis read from the entity.
Returns any — The play handle.
local h = effects.playOn("explosion", drum, { params = { scale = 3 } })
globals/effects/registerBackend
effects.registerBackend(kind: string, backend: table)
Register a new way of drawing under a kind name, so an effect family
that needs one the runtime does not ship adds it rather than widening the
runtime. Every effect reaches it through ctx.lease(kind, spec).
Parameters
kindstring— The kind name a spec asks for.backendtable— The backend —key,acquire,seat,start,stop,quiet,place,bytes,active,silenceandfree.
effects.registerBackend("ribbonTrail", myBackend)
globals/effects/silenceReasons
effects.silenceReasons() -> { { reason: string, means: string } }
The closed set of reasons a play can be producing nothing, in the order
a reading resolves them — nearest cause first — each with what it means.
Every reason an observation reports is one of these.
Returns { { reason: string, means: string } } — Array of { reason, means }.
for _, r in ipairs(effects.silenceReasons()) do print(r.reason, r.means) end
modules/effects/README
require("@builtin/modules/api/engine/effects") -- effects (also available as global 'effects')
Fire a finished visual effect from gameplay code in one line. play puts an effect at a position and playOn sticks it to an entity; both return a handle that stops it early, moves it, or re-tunes a parameter while it runs. The effect owns its own lifetime — nothing here needs the caller to tick it — and repeated firing re-uses what the last one left rather than allocating again.
Usage: local effects = require("@builtin/modules/api/engine/effects") Also available as global: effects
modules/effects/backends
backends(): { string }
The backend kinds an effect can be built out of, in name order. The
runtime ships emitter, geometry, material, decal and feature.
print(table.concat(effects.backends(), ", "))
modules/effects/describe
describe(identity: string): { [string]: any }
What an effect declares about itself: its family, a one-line summary, every parameter with its type, default and documented range, and the cost one unpooled play of it was measured to draw. The one call to make against an unfamiliar effect before playing it.
Parameters
identitystring— The effect's canonical identity, or a short name.
local d = effects.describe("explosion"); print(d.family, d.cost.gpuMs)
modules/effects/drain
drain(): { [string]: number }
Free every backend the pool is holding idle. The pool keeps what it has leased for as long as the engine runs — that is what makes repeated firing cost nothing after the first — and this is the one call that gives it back. A backend a live play still holds is left to that play's own end.
print(effects.drain().freed)
modules/effects/families
families(): { string }
Every family the effects in this world declare, sorted — the values
list { family = … } filters on. An effect declaring no family is not one
of them.
for _, f in ipairs(effects.families()) do print(f, #effects.list({ family = f })) end
modules/effects/list
list(opts: table?): { string }
The canonical identity of every effect this world can play, sorted.
These are the exact strings play takes. Pass { family = "combat" } to
get only the effects of one family — the catalogue filtered the way an
effect declares itself.
Parameters
optstable?(optional) —{ family? = string }. A family is matched without regard to case.
for _, id in ipairs(effects.list()) do print(id) end
for _, id in ipairs(effects.list({ family = "combat" })) do print(id) end
modules/effects/observe
observe(): { [string]: any }
What the runtime is holding and driving right now — every live play with
the reason it is silent when it is, plus what the pool has leased out and
what it is keeping idle, in instances and in GPU bytes. This is how a caller
and a test tell a working effect from a silent one, and how they tell a pool
warming to a wider burst from something leaking: the pool is sized by the
most effects it has had to cover at once, which peakLive and peakLeased
report beside the current totals.
local o = effects.observe(); print(o.live, o.leased, o.pooled, o.bytes)
print(o.peakLive, o.peakLeased) -- the widest burst the pool covers
modules/effects/play
play(identity: string, opts: table?): any
Play an effect once at a world position. The effect allocates what it needs from the shared pool, draws itself, and gives everything back when it ends — with no update loop on the caller's side.
Parameters
identitystring— The effect's canonical identity, or a short name that reaches exactly one effect.optstable?(optional) —{ position? = { x, y, z }, rotation? = quat, direction? = { x, y, z }, params? = { … }, duration? = number, held? = boolean }. Anythingparamsomits takes the effect's declared default, and an effect that declares adurationparameter reads its length from there rather than fromdurationhere.
local h = effects.play("@builtin::systems.effects.combat.explosion", {
position = { 0, 2, 0 }, params = { scale = 4, coreColor = { 1, 0.4, 0.1 } },
})
modules/effects/playOn
playOn(identity: string, target: any, opts: table?): any
Play an effect on an entity: it starts where the entity stands and ends
if the entity leaves the world. Move it with the entity by calling
handle:retarget(theEntity) as it goes.
Parameters
identitystring— The effect's canonical identity, or a short name.targetany(optional) — An entity proxy or entity id.optstable?(optional) — The same optionsplaytakes;positionis read from the entity.
local h = effects.playOn("explosion", drum, { params = { scale = 3 } })
modules/effects/registerBackend
registerBackend(kind: string, backend: table)
Register a new way of drawing under a kind name, so an effect family
that needs one the runtime does not ship adds it rather than widening the
runtime. Every effect reaches it through ctx.lease(kind, spec).
Parameters
kindstring— The kind name a spec asks for.backendtable— The backend —key,acquire,seat,start,stop,quiet,place,bytes,active,silenceandfree.
effects.registerBackend("ribbonTrail", myBackend)
modules/effects/silenceReasons
silenceReasons(): { { reason: string, means: string } }
The closed set of reasons a play can be producing nothing, in the order
a reading resolves them — nearest cause first — each with what it means.
Every reason an observation reports is one of these.
for _, r in ipairs(effects.silenceReasons()) do print(r.reason, r.means) end
typed/builtin//modules/api/engine/effects/effects/backends
effects.backends() -> { string }
The backend kinds an effect can be built out of, in name order. The
runtime ships emitter, geometry, material, decal and feature.
Returns { string } — Array of kind names.
print(table.concat(effects.backends(), ", "))
typed/builtin//modules/api/engine/effects/effects/describe
effects.describe(identity: string) -> { [string]: any }
What an effect declares about itself: its family, a one-line summary, every parameter with its type, default and documented range, and the cost one unpooled play of it was measured to draw. The one call to make against an unfamiliar effect before playing it.
Parameters
identitystring— The effect's canonical identity, or a short name.
Returns { [string]: any } — { identity, family, summary, cost, params }.
local d = effects.describe("explosion"); print(d.family, d.cost.gpuMs)
typed/builtin//modules/api/engine/effects/effects/drain
effects.drain() -> { [string]: number }
Free every backend the pool is holding idle. The pool keeps what it has leased for as long as the engine runs — that is what makes repeated firing cost nothing after the first — and this is the one call that gives it back. A backend a live play still holds is left to that play's own end.
Returns { [string]: number } — { freed, kept }.
print(effects.drain().freed)
typed/builtin//modules/api/engine/effects/effects/families
effects.families() -> { string }
Every family the effects in this world declare, sorted — the values
list { family = … } filters on. An effect declaring no family is not one
of them.
Returns { string } — Array of family names.
for _, f in ipairs(effects.families()) do print(f, #effects.list({ family = f })) end
typed/builtin//modules/api/engine/effects/effects/list
effects.list(opts: table?) -> { string }
The canonical identity of every effect this world can play, sorted.
These are the exact strings play takes. Pass { family = "combat" } to
get only the effects of one family — the catalogue filtered the way an
effect declares itself.
Parameters
optstable(optional) —{ family? = string }. A family is matched without regard to case.
Returns { string } — Array of identities.
for _, id in ipairs(effects.list()) do print(id) end
for _, id in ipairs(effects.list({ family = "combat" })) do print(id) end
typed/builtin//modules/api/engine/effects/effects/observe
effects.observe() -> { [string]: any }
What the runtime is holding and driving right now — every live play with
the reason it is silent when it is, plus what the pool has leased out and
what it is keeping idle, in instances and in GPU bytes. This is how a caller
and a test tell a working effect from a silent one, and how they tell a pool
warming to a wider burst from something leaking: the pool is sized by the
most effects it has had to cover at once, which peakLive and peakLeased
report beside the current totals.
Returns { [string]: any } — The observation.
local o = effects.observe(); print(o.live, o.leased, o.pooled, o.bytes)
print(o.peakLive, o.peakLeased) -- the widest burst the pool covers
typed/builtin//modules/api/engine/effects/effects/play
effects.play(identity: string, opts: table?) -> any
Play an effect once at a world position. The effect allocates what it needs from the shared pool, draws itself, and gives everything back when it ends — with no update loop on the caller's side.
typed/builtin//modules/api/engine/effects/effects/playOn
effects.playOn(identity: string, target: any?, opts: table?) -> any
Play an effect on an entity: it starts where the entity stands and ends
if the entity leaves the world. Move it with the entity by calling
handle:retarget(theEntity) as it goes.
Parameters
identitystring— The effect's canonical identity, or a short name.targetany(optional) — An entity proxy or entity id.optstable(optional) — The same optionsplaytakes;positionis read from the entity.
Returns any — The play handle.
local h = effects.playOn("explosion", drum, { params = { scale = 3 } })
typed/builtin//modules/api/engine/effects/effects/registerBackend
effects.registerBackend(kind: string, backend: table)
Register a new way of drawing under a kind name, so an effect family
that needs one the runtime does not ship adds it rather than widening the
runtime. Every effect reaches it through ctx.lease(kind, spec).
Parameters
kindstring— The kind name a spec asks for.backendtable— The backend —key,acquire,seat,start,stop,quiet,place,bytes,active,silenceandfree.
effects.registerBackend("ribbonTrail", myBackend)
typed/builtin//modules/api/engine/effects/effects/silenceReasons
effects.silenceReasons() -> { { reason: string, means: string } }
The closed set of reasons a play can be producing nothing, in the order
a reading resolves them — nearest cause first — each with what it means.
Every reason an observation reports is one of these.
Returns { { reason: string, means: string } } — Array of { reason, means }.
for _, r in ipairs(effects.silenceReasons()) do print(r.reason, r.means) end