An entity is an opaque ID with at most one component of each type. spawn
creates one component-bearing entity; add attaches another component. A
system selects component types and gives its callback typed, mutable bindings
for each match. This is the step from value to type to ECS: the type owns
state and behavior, while the system owns the update schedule.
Schedule a component
Compile the counter fixture, then use Step and Finish. init prints
init once for the matching counter, the first step appends 1, and done
prints once when Finish completes. Reset starts a new run at tick zero.
Show a QR code for your glasses, or send a link to another browser. You can keep working here.
Sharing starts a fresh run of the last compiled code. Your editor draft stays here.
Join a session
Open an invitation link, or paste a link or code from the other device.
On RayNeo, open Menu → Connect live and scan this code. In another browser, open the invitation link below.
Or enter this code:
Waiting for another device. You can keep working while it connects.
Browsers can edit code; every device can use scene controls. The device that started the session controls playback.
Connection settings
A full invitation link includes its host. With a code alone, both devices need the same live host. Pairing setup
No output.
- Executed source spans appear here.
system Tick of Counter selects one component and addresses it as self.
system Rotate of (spinner: Spinner, pose: Transform) selects entities with
both distinct concrete types and names the bindings. A successful callback
writes every changed binding back together. Misspelled fields and wrong method
arguments fail compilation; there is no string lookup or cast. A single
selector may name a trait, but trait joins and optional components are not
implemented.
Lifecycle and world access
frame(dt) is required. init() runs before the first frame for each matching
tuple, and done() runs when an initialized tuple is removed or the host
finishes the run. entity, time, and tick identify the current match and
simulation clock. despawn is deferred to the callback or action boundary, so
teardown sees committed values and a removed entity receives no later frame.
Outside a system, use get[T](entity) to copy a statically selected component,
edit the copy, and set(entity, copy) to persist it. query[T]() returns
stable entity IDs, while has[T](entity) tests membership. add attaches a
missing component. Invalid world operations remain runtime checks.
Systems run in linked source order, imported modules before their importers. Each system snapshots its matches at the start of its visit and traverses them by entity ID. Later systems see accepted changes from earlier systems; no systems run in parallel.
Edit exercise
Change the increment in Counter.advance from 1 to 2. After two steps,
the inspected counter value should be 4; Finish should still invoke done
once. Replace the frame callback’s dt: Number with dt: Bool and compilation
should report the required lifecycle signature.
Initialization, actions, ticks, and finish are transactions. A failed operation rolls back component edits, globals, logs, entity IDs, and lifecycle membership. The language reference has the exact ordering and runtime rules; the built-in catalog documents ECS operations.