Skip to content

@awaken/runtime ​

Everything that runs while your game plays: the physics engine (Rapier), the script host, the play/scene lifecycle, input, audio, in-game UI, and skeletal-animation playback. It depends on @awaken/core and Rapier (WASM) - not on @awaken/render, so the whole runtime is headless-testable.

ts
import { Runtime, PlayController, ScriptHost, RigidBody, Collider, RapierBackend } from "@awaken/runtime";

The Scripting API is the user-facing surface over this package; the Physics section covers the physics feature set. This page is the underlying types.

runtime (systems) ​

SymbolSignatureDescription
System(world, dt) => voidA per-frame simulation function.
RuntimeclassHolds an array of Systems; tick(world, dt) runs them in order.
DEFAULT_SYSTEMSSystem[] ([])Empty by default - gameplay lives in scripts (the ScriptHost) and physics is driven by the PhysicsRunner, not built-in tick systems.

The play lifecycle ​

PlayController owns Edit → Play → Stop. On Play it snapshots the scene, builds the physics sim + script host, and starts play-on-start audio; on Stop it tears them down and restores the snapshot (optionally keeping your authored edits). See Preview & Play.

SymbolSignatureDescription
PlayState"edit" | "play" | "paused"The controller's state.
PlayControllerclassplay(), pause(), resume(), stop(keepEdits?), update(dt), state, markEdited()/hasEdits(), requestRestart(). Constructed with the world, Runtime, component types, and optional services (registry, audio, hud, physics, ui, scenes, game, prefab source, log sink).

update(dt) runs the frame in order: apply any queued scene swap → step physics → run systems → run scripts (which see updated transforms + real contacts) → sync script/animation-moved colliders back into physics.

Scripting ​

The script host runs each entity's Script behaviours and exposes the ScriptApi to them. Script parameters are discovered from the compiled class so the Inspector can edit them.

SymbolSignature / ShapeDescription
ScriptApiinterfaceThe full script-facing surface: transform helpers, find/findByTag, spawn, events (emit/on), timers (after/every), loadScene/reloadScene, save/load/state, moveAndSlide, raycast, playSound, setHud, ui, log. Documented field-by-field in Scripting API.
ScriptBehaviorinterfaceThe lifecycle hooks a script implements: onStart, onUpdate(api, dt), onDestroy, onCollision/onCollisionEnter/onCollisionExit.
ScriptComponentType + interface{ scripts: ScriptEntry[] } - an entity can carry several behaviours.
ScriptEntry{ name; params?; refs?; enabled? }One attached behaviour: its script id, per-instance parameter overrides, entity-reference fields, and enable flag.
TagComponentType + interface{ value: string } - a string tag for findByTag lookup (find by tag, not by name).
ScriptParam{ name; type; default; component?; options?; description?; min?; max? }A discovered public field (drives the Inspector control).
discoverScriptParams(factory, source?) => ScriptParam[]Discover a script's editable public fields by combining instance introspection + source parsing (TS types are erased at runtime).
ScriptRegistryclassregister(name, factory), get, unregister, names() - the compiled-script lookup.
ScriptHostclassRuns the behaviours: update(world, dt, contacts?) and destroyAll(world). Owns per-slot instances, timers, event handlers, and collision-edge tracking; hot-restarts a slot when its params change during Play.
SpawnFn(prefab, opts?) => Entity | nullPrefab instantiation hook the app supplies.

See Script Parameters, Events & Timers, and Input.

Physics ​

Physics is engine-agnostic: Awaken talks only to PhysicsBackend/PhysicsWorld, implemented today by Rapier (WASM). The ECS components author the bodies; the PhysicsRunner builds and steps the sim during Play.

Components ​

SymbolSignature / ShapeDescription
RigidBodyComponentType + interface{ velocity, useGravity, restitution } (defaults: 0 velocity, gravity on, restitution 0.3).
ColliderComponentType + interface{ shapes: ColliderShape[] } - one body, many shapes.
ColliderShape{ kind, center, size, radius, height, mesh, convex, trigger, enabled, pinned? }One shape: a primitive or a collision mesh, each independently a trigger/solid/toggleable.
ColliderKind"box" | "sphere" | "capsule" | "cylinder" | "mesh"Shape kind.
newColliderShape(kind?) => ColliderShapeConstruct a default shape.
primaryShape(c) => ColliderShapeThe first enabled shape (drives the AABB fallback + character capsule).
GRAVITY-9.81Default gravity constant.
detectCollisions(world) => [Entity, Entity][]Pure AABB overlap test - the fallback when no physics engine is running.
physicsSystemSystemThe legacy hand-rolled semi-implicit-Euler integrator (superseded by the Rapier runner in Play).

See Rigidbody, Colliders, and the Character Controller.

Backend & runner ​

SymbolSignatureDescription
PhysicsBackendinterface{ name, supportsSoftBody, init(), createWorld(gravity) } - a physics engine implementation.
PhysicsWorldinterfaceA live sim: step, bodies, colliders, joints, raycast, drainContactEvents, moveCharacter, and debug line geometry.
RapierBackendclass implements PhysicsBackendThe Rapier (WASM) implementation.
PhysicsRunnerclassBridges the ECS to a PhysicsWorld: prewarm, start(world), addEntity, step(world, dt), syncColliderPoses, contacts(world), moveCharacter, raycastForScript, plus debugLines/debugTriggers for the physics debug view.
createMeshShapeFor(…) => ShapeDesc | nullBuild a convex-hull/trimesh collision shape from a mesh.
BodyType, ShapeDesc, BodyDesc, ColliderDesc, JointDesc, JointMotor, JointSpring, RaycastHit, ContactEvent, CharConfigtypesThe backend's descriptor + event vocabulary (see Joints, Queries & Events).

Scenes & state ​

SymbolSignatureDescription
SceneDirectorclassThe runtime scene library + deferred transition queue. register/registerAll, load(name), reload(), take() (drained each frame by the PlayController). Loads apply at the top of the next frame, never mid-script.
GameStateclassstate (in-memory session bag surviving scene loads) + save(key, value)/load(key) (namespaced localStorage) + resetSession().
KVStoreinterface{ getItem, setItem, removeItem } - the storage abstraction, so save/load is testable without a browser.

See Scenes & Persistence.

Input ​

SymbolSignatureDescription
InputclassPer-frame input: isDown(key), mouseDX/mouseDY (per-frame delta for mouse-look), pointerLocked, plus the setters the game loop drives (setKey, addMouse, clearMouse, setPointerLocked, clear).

Scripts read this via api.input. See Input.

Audio ​

SymbolSignatureDescription
AudioEngineinterface{ play(clip, opts?) } - pluggable so the runtime stays headless-testable.
NoopAudioEngineclassThe headless no-op backend.
PlayOpts{ volume?, loop? }Playback options.
AudioSourceComponentType + interface{ clip, volume, loop, playOnStart } - an entity that plays an imported sound on Play start.
BrowserAudioEngineclassThe Web Audio backend, shared by the editor and the exported player: addSound, play (returns a handle), stop, stopAll.

See Audio.

In-game UI ​

SymbolSignatureDescription
UINodeComponentType + interfaceA screen-space UI element (kind: text | panel | button | image, anchor, x/y/w/h, text, fontSize, color, bg, opacity, visible, and - for image and animation - image/fit/rotation/scaleX/scaleY/font). Rendered as a DOM overlay in both the editor Game view and the shipped player.
uiNodeStyle(n: UINode, scale?) => CSSPropsPure UINode → CSS map (one source of truth, unit-testable). scale multiplies every pixel dimension (the overlay passes viewportHeight / uiReferenceHeight).
UIAnimatorComponentType + interface{ clip, playing, speed, time } - plays a UIClip on a widget's UINodes (tracks address them by name).
driveUIAnimators(world, dt, clipById) => voidAdvance every UIAnimator and write its clip's sampled values onto the widget's UINodes. Call once per frame before the overlay syncs.
applyUIClip(clip, time, resolve) => voidSample every track of a UIClip at time and write the values onto the resolved target nodes (loops if the clip loops).
sampleTrack / clipDurationhelpersLinear-interpolate a keyframe list at t; the latest keyframe time across a clip's tracks.
UIClip / UITrack / UIKey / UIProptypes (re-exported from @awaken/core)The renderer-agnostic keyframe model a UIAnimator plays (imported from Unity .anim).
HudSink / NoopHudSinkinterface / classThe HUD-text sink (api.setHud).
UIStateclassButton-click handler registry (api.ui.onClick), fired by the overlay.
UIOverlayclassThe DOM overlay that renders UINodes and dispatches clicks to UIState.

Scripts drive UI through api.ui: setText / setImage / show / hide / onClick, plus play(name, clip) / stop(name) for UI animation. See UI and Scripting UI.

Animator & animation system ​

SymbolSignatureDescription
AnimatorComponentType + interfacePer-entity playback state: clip/skeleton/time/speed/loop/playing, the crossfade fields (fadeClip/fadeTime/fadeDuration/fadeElapsed), the play window (clipStart/clipEnd), and root-motion output (rootDx/rootDz, flatRootY).
playClip(anim, clip, opts?) => voidStart playback, crossfading over opts.fade (blends the two clips via core blendPoses); idempotent.
advanceTime / advanceTimeRangeclock helpersAdvance a playback clock (loops both directions; non-looping clamps); the Range form trims to a [start,end] window.
animationSystem(world, dt, deps: AnimationDeps) => voidAdvance every Animator, crossfade-blend, extract root motion, apply foot IK, CPU-skin its mesh, and upload the deformed positions; also writes bone-anchor poses and builds/drives a ragdoll when one is flagged.
AnimationDepsinterface{ clip, skeletonFor, skinFor, upload, footIK? } - outside-the-ECS dependencies, injected for testability (footIK supplies the ground source + config).
AnimStateMachine / animGraphSystemComponentType / (world, deps) => voidParam-driven state graph that chooses the Animator's clip; LOCOMOTION_GRAPH is a built-in. Drives via api.setAnimParam/setAnimTrigger.
BoneAnchorComponentTypeMirrors one named skeleton bone onto an entity so attachments ride the animation.
Ragdoll / buildRagdollBodies / ragdollBoneMatricescomponent + helpersHands a skinned character to physics (joint-linked bodies) and drives the skeleton from the sim. Experimental.

| applyFootIK / FootIKConfig | (skel, pose, cfg, groundY, weight?) => Mat4[] | Two-bone leg IK, pelvis adjust and plant weight, grounding a planted foot. A per-frame solver, so it sits here rather than in core; only quatFromTo (shared with the ragdoll) is core math. |

The pure skinning, blend, root-motion and graph math lives in @awaken/core. See Animation.

Particle engine ​

SymbolSignatureDescription
ParticleEngineclassOwns every live emitter pool and every in-flight one-shot burst. tick(world, dt) advances each active ParticleEmitter (and each burst), simulating via simulateEmitter and uploading through deps. burst(effectId, opts?) spawns a transient one-shot that retires itself once exhausted. clear() drops everything.
EmitterStateSoA poolOne emitter's live particles (position, velocity, life, rotation, size arrays) plus a seeded PRNG. Side-state, never serialized.
makeEmitterState(cfg, seed?) => EmitterStateAllocate a pool sized to cfg.maxParticles with a deterministic PRNG, never Math.random.
simulateEmitter(state, cfg, dt, worldMatrix, out) => countAdvance by dt and write count x PARTICLE_FLOATS floats into out; returns the live count. out must hold state.capacity x PARTICLE_FLOATS.
ParticleDepsinterface{ effect(id), upload(handle, data, count, opts), remove(handle) } - the seam that keeps @awaken/runtime free of any renderer or asset-store import. effect resolves an id against the project; upload/remove are backed by the renderer's particle buffers.

Pools are side-state keyed by entity: they are never serialized, and they bypass the ECS dirty-set entirely - the same rule CPU skinning follows, so a per-frame particle update never triggers a draw-cache rebuild. A burst is deliberately not tied to the script that fired it, so destroying an object mid-frame doesn't cut off its own explosion. See Particles.

See also ​

  • Scripting API - the user-facing surface over ScriptApi/ScriptBehavior.
  • Physics Overview - the physics feature set backed by PhysicsRunner/Rapier.
  • Component Reference - RigidBody, Collider, Script, Tag, AudioSource, Animator, UINode, UIAnimator fields.
  • Preview & Play - the play lifecycle PlayController drives.
  • @awaken/core - the World, Entity, and animation math the runtime builds on.

Awaken — browser-native WebGPU game engine.