v0.12.2
Particle Rendering Fix
The particle system failed to render in v0.12.1 — vertex data never reached the GPU. This release rewrites the particle render path:
- ParticlePlugin now builds rotated quads directly into TransientBufferPool during
collect(), using the standard DrawCommand path - Eliminates per-emitter intermediate heap allocations
- New
CMD_STATE_CUSTOM_DRAWflag on DrawCommand makes custom draw extensible instead of hardcoding RenderType checks
Extensible Asset Handlers
New registerAssetHandler() API lets plugins register custom asset type handlers:
- Scene loading no longer hardcodes asset field handling logic
- Builtin handlers (texture, Spine, material, font, etc.) lazy-initialize via
builtinAssetHandlers.ts - Plugins can call
registerAssetHandler()inbuild()to register custom asset types
Cross-Platform devicePixelRatio
PlatformAdapter interface now includes a devicePixelRatio() method:
- Web and WeChat Mini Game platforms provide native implementations
- Replaces platform-specific branching previously in
base.ts
Memory Leak Fixes
Fixed multiple WASM memory leaks when entities are despawned:
- Timeline/Tween: C++ timeline objects and tween entities were not freed on entity despawn — now automatically calls
_tl_destroyandTween.cancelAll()viaonDespawn - Spine: SpineManager was not cleaned up on entity despawn — now automatically calls
SpineManager.removeEntity() - Audio: audio handles were not stopped or released on entity despawn — now automatically stops and cleans up
- Font resources: font resources were not released on scene unload — now cleaned up via
releaseFont()
ECS Stability Improvements
Commands Exception Isolation
Commands.flush() now wraps each pending command in try-catch — a single command throwing no longer silently skips remaining commands in the queue.
Query Mut Entity Validation
Query Mut write-back paths (both iterator and forEach) now validate entity existence before writing back mutations, preventing crashes when entities are despawned mid-iteration via deferred Commands.
ScriptStorage Validation
ScriptStorage.set() now validates component data against schema (warn level), catching invalid data in hot iteration paths.
Scene and Plugin Error Recovery
- Scene loading now cleans up already-created entities when component deserialization fails, preventing half-initialized entities from lingering
- Plugin
build()failures now trigger automatic rollback — the plugin is removed frominstalledPluginSet_,installed_plugins_, andinstalledPluginNames_
Internal Improvements
- Eliminated module-level singletons: CollectionViewPlugin, TimelinePlugin, and PostProcessStack global state moved into plugin/class instances
- Unified asset discovery via
discoverSceneAssets()— scene loading, preloading, and runtime loading share a single discovery function - PostProcessStack dirty flag skips WASM sync when no mutations occurred
- MaterialCache extracted from static globals into EngineContext with proper lifecycle cleanup
- 11 UI plugins now declare explicit plugin dependencies, leveraging topological sort for initialization order
Bug Fixes
- Fixed async startup systems potentially executing twice under concurrent
tick()calls — added reentrant guard - Fixed web
fileExistsfalse positive under Tauri custom protocol — Tauri returns 200 for all HEAD requests, switched to GET + body cancel - Fixed Windows build failure when invoking
emcmake.bat—.batfiles requirecmd.exe /Cshell execution - Fixed Windows build failure when
emcmake.batpath contains spaces — path is now quoted - Fixed uniform buffer overflow writing out of bounds — overflow guard moved before writes