Log inGet started
What it does

effects — fire a finished effect in one line

effects is the global gameplay code reaches for when something should happen on screen and then be gone. It plays the effect assets the catalogue carries, owns their lifetime, and re-uses what the last shot left rather than allocating again.

local h = effects.play("@builtin::systems.effects.combat.explosion", {
    position = { 0, 2, 0 },
    params   = { scale = 4.0, coreColor = { 1, 0.4, 0.1 } },
})

That is the whole call. Nothing ticks it, nothing tears it down.

The calls

CallWhat it does
effects.play(identity, opts)Play once at a world position.
effects.playOn(identity, entity, opts)Play seated on an entity; ends if the entity leaves the world.
effects.list()Every canonical identity this world can play.
effects.describe(identity)Family, summary, every parameter with its type/default/range, and the measured cost.
effects.observe()Live plays, what the pool holds, and why a play is producing nothing.
effects.silenceReasons()The closed set of reasons a play produces nothing.
effects.drain()Free every backend the pool is holding idle.
effects.backends()The backend kinds an effect can be built out of.
effects.registerBackend(kind, backend)Add one.

The handle

h:stop()                      -- stop producing; what is drawing finishes naturally
h:cancel()                    -- stop and take it away now
h:retarget(positionOrEntity)  -- move it
h:setParam(name, value)       -- re-tune a declared parameter while it runs
h:isPlaying()                 -- still producing or still drawing
h:isFinished()                -- ended and gave back everything it held
h:stats()                     -- what it is doing, in numbers to assert on
h:whySilent()                 -- reason, detail — or nil while it is producing

h:setParam carries whatever the effect declares: a number, a range, a colour, a vec2, a vec3, an entity or a flag. A beam's endpoints and an impact's host are not scalars, and the channel carries them as themselves.

Cost, and the pool

Building an emitter is expensive and its VRAM is allocated per declared slot, whether or not those slots are ever filled — which is why one emitter per shot churns the renderer. The runtime leases every backend an effect is made of from one shared pool: the first play allocates, and every play after it re-seats what the last one gave back.

The pool is sized by concurrency, not by shot count. It grows to the highest number of effects it has had to cover at the same time and then holds there. Five at once allocate for five; the sixth round of five allocates nothing. observe() reports peakLive and peakLeased beside bytes for exactly this: a total climbing alongside the peak is a pool warming up, a total climbing while the peak stands still is a leak.

The retention policy is explicit. The pool keeps what it has leased for as long as the engine runs and returns it on effects.drain() and nowhere else. There is no idle timer. effects.observe() reports leased, pooled and bytes so a caller can see what is being held.

When nothing appears

Ask. effects.observe() and handle:whySilent() answer from a closed set:

ReasonMeans
finishedThe play has run out and given back everything it held.
noBackendsThe effect staged nothing at these parameters.
targetMissingThe entity the play was seated on has left the world.
notSimulatingThe engine is not advancing the simulation, so nothing emitted moves or draws.
noCameraNo camera is rendering the scene.
backendSilentEverything the play holds is allocated and producing nothing; the detail names which.

notSimulating is the one to expect first: particles advance on the play clock, so an effect fired in edit mode holds live particles and submits nothing.

See also

  • guides { topic = "visual-effects" } — the whole topic, including authoring.
  • man /zero/source/libs/@builtin/assetTypes/effect.assetType — what an effect asset carries.
  • man /zero/source/libs/@builtin/systems/effects.package — the runtime, its backends and its pool.

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

This asset doesn't declare a schema or structured payload.

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

0items
This part has no composite children. See the Files segment for its leaf payloads.
This part has no leaf payloads.

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported. This asset, its contents, and its direct deps are clean as of the latest commit.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.