Repository navigation
A large release: 926 commits across 71 issues since v0.7.2. The headline is nested prefab identity, a rework of how prefab and scene files store nested edits. It is paired with a new gameplay recorder, a round of undo, Play and preview safety fixes, and a cleanup of the agent (MCP) tool surface, which includes breaking renames.
✨ Features
Nested prefabs keep their identity
Every prefab member and node now carries a stable, stored identity, and nested edits are saved on the member they belong to. Previously, edits were keyed by position in the hierarchy.
- New file formats: prefab v5 → v7 and scene v16 → v17. Existing files migrate on load. Older editors refuse a newer file rather than silently corrupting it, and the prefab writers no longer stamp a format version unconditionally.
- Moves, field overrides, added tags, added/removed nodes and removed traits on nested instances are saved per member and per node. Editing one object no longer pins its untouched siblings, and later template changes still reach everything you didn't edit.
- Apply / Revert name members by identity, so they survive renames, re-parenting and rebuilds across two template versions. Apply from a nested instance keeps values the outer row shadows. The Apply dialog and the Inspector's override list show only an instance's own edits.
- Template reference nodes (a prefab placed inside a prefab template) now save their own moves, rows and references correctly, and keep orphaned rows.
- A member whose template node is gone is kept and named, never silently dropped (orphan rows survive Refresh and rebuilds at any depth).
- Duplicating a scene, promoting an instance, and Create Prefab in the same session all preserve member identity. Previously, a member moved in a just-created prefab was lost on reload.
- A rigged re-import no longer discards the prefab fields it doesn't compute.
Gameplay recorder
- Record a take in the GameView, then render it to video. Stop opens a render-options dialog, and a non-modal card shows render progress with cancel. You can also render from the CLI with
npm run record. - Replays are deterministic: fixed-timestep capture, a pinned RNG seed, and scene loads that cost zero take time.
- Each render is checked against the take's recorded events, per event type with numeric tolerance. Boot-time and app-lifetime events are handled so a correct replay doesn't read as diverged.
- A render names any assets that changed since the take was recorded, and survives a Vite page reload during boot.
- The GameView preview now lays out at the full device size.
Audio
- A new audio-health trace reports when the music bed is lost.
- Projects can opt in to reloading the page when audio is dead (running but frozen).
- Fullscreen ads hold the engine's audio and release it safely. A refused media play is recorded instead of swallowed.
Native plugins
- AppLovin MAX (
capacitor-applovin-max) meets the engine's ad contract: UMP consent, adaptive banners, and bounded preloads. Every parked call settles, including loads during MAX's expiry reload and repeat initializes. - In-app purchases (Android): every Billing listener settles its call, so a routine service disconnect can no longer hang a purchase or block later ones. The products/entitlements race on a shared array is fixed.
- game-debug (iOS):
startServeranswers exactly once on every path, and a failed start still registers recovery.requestReviewcan't crash. - AppsFlyer: the ATT request waits for the app to be active, and an already-answered status no longer blocks ads from starting.
- Boot diagnostics: the boot timeline records what the OS was doing, and the stall log says so.
🤖 Agent / MCP tooling
scene_query→physics_queryon both servers.- One word per concept across the surface (
path/type/kind/t/time). - An aim that names more than one of entity / selector / label /
{x,y}is refused as AMBIGUOUS instead of being resolved by precedence. - Action tools (for example
play_control) reply with the fields they changed, not the whole editor state.
Improvements
- String-encoded arguments (
"12","true", a JSON object) are decoded rather than refused, including game tool calls. Out-of-range numbers are refused by the schema instead of being clamped. - Tool descriptions are about 10 KB shorter, with repeated schema prose and history removed.
get_scene_state'strait=selects carriers, and targeted reads are capped at 20, with the cap disclosed.list_actions/device_introspectreturn bare names, andname=<substr>returns param schemas.- Reading a journal no longer clears it (a
sinceCap/nextSeqbaseline replaces clear). - Device ↔ editor parity: one console reader for both,
levelas a threshold,sinceas a sequence cursor andsinceMsas the clock. There is adevice_wait_fortwin that waits on entities and console output, anddevice_duplicate_entityaccepts the same entity alias. - Native-log windows are honoured on both platforms, and refusals name the next move.
- Entity aims sample the part of the rect the surface actually draws, and 2D bounds report their draw rect. A covering game UI node is named as its entity rather than as dock chrome.
- Handle routes share the aimed-route refusal contract.
- The play op reports a refused Play instead of
ok: true.modoki_dndreports a drop that opened a modal aspendingModal. save_allnames every file in asset-root form.- Strict-schema refusals name the unknown key.
- On Android, trusted CDP touches pick the app's page by identity, so taps reach the game.
🐛 Fixes
Undo, Play and preview
- A Timeline/Animation preview session and Play never coexist. Play, Stop and scene loads end the preview through one path, and they share one authored snapshot and restore.
- A preview puts back the audio mix, PlayerPrefs and quality tier its actions changed.
- A scrub, a Play press, or undo/redo during Stop's restore is refused until the restore lands. Leaving a preview cancels a session begin that is still pending.
- Every writer of the live world asks one question, "is the world authored?", so save-all during a restore can't write the posed state.
- Clip undo no longer opens a preview with no panel to exit it, and record mode bakes every recorded value, not just the first.
- Pausing the Animation ▶ freezes playback instead of leaving it advancing.
- Undo of an Apply made in the prefab editor, or in an untitled scene, now rebuilds the live instances, not just the prefab file.
- Opening a scene or prefab waits for an undo in flight, and the unsaved-changes prompt reads the post-undo state.
- A refused or non-reverting toolbar Play/Stop shows a warning toast with the reason.
Editor
- SceneView gizmo: aiming, picking and dragging use one camera and draw area, and axis handles are hit where they are drawn.
- Save As no longer pairs an
/assets/copy with an/@fs/source. JSON asset routes never overwrite an asset of a different kind. - The save dialog, the Inspector's Apply/Revert, and the hot-reload banner buttons are properly named (accessibility and automation).
- Quitting the editor commits renderer storage first, so the remembered layout and scene survive a stop.
editor:stopno longer kills the quit sequence with a double SIGTERM.
Build and dev server
- The editor no longer boots a game degraded after a dependency changes: each project's lockfile now keys Vite's dep-optimizer cache.
- A game's packages are pre-bundled at startup (cold dev boot no longer reloads mid-boot), and an inert packaged pre-bundle entry that warned on every boot is gone.
build.debugBuildoff removescapacitor-game-debugfrom the native build entirely, and re-enabling it restores it where it was.- A freshly scaffolded project builds, and the starter template is typechecked on every run.
Windows
- Open / Reveal in Explorer works with
&, spaces and paths the shell can't open. It no longer runs part of a file name as a command, opens Documents, hangs on a modal, or reports failure on success. - Build steps no longer go through a shell (argv everywhere,
.cmd/.batrun with escaping), so%VAR%in a path no longer expands.
⚡ Performance
- pixi.js 8.20.1 → 8.21.0, which carries the upstream fixes for two known memory leaks. The engine's
unload()workaround is removed. - Prefab identity resolution builds its world-wide lookup once per resolver instead of per query.
Full Changelog: v0.7.2...v0.7.3