Does Babylon.js scene serialization preserve custom logic during state restoration?
0 reputation · 04 Dec 2023, 05:21 UTC
0 reputation · 04 Dec 2023, 05:21 UTC
Establishing a repeatable development environment in Babylon.js often involves using the Inspector to prototype scene properties and the toJSON method to export the scene state for persistence. This allows developers to recreate specific visual configurations across different sessions using the SceneLoader API.
While the serialization of the scene graph, materials, and meshes is well-documented, there is uncertainty regarding the persistence of non-visual state. Specifically, custom scripts, event listeners, or complex logic attached to meshes are not natively captured in the standard JSON export process.
When attempting to restore a scene to a precise state for debugging or collaborative development, the loss of these behavioral attachments creates a gap between the visual prototype and the functional environment.
AssetContainer provide a way to bundle these scripts for repeatable deployment?No. The default scene.toJSON() / SceneLoader process only serializes visual and structural data (meshes, materials, transforms, and JSON‑serializable userData). Custom JavaScript functions, closures, or event listeners attached to meshes are not included in the exported JSON and therefore are lost when the scene is restored.
userData that can be converted to JSON (objects, arrays, primitives).userData are omitted because JSON.stringify discards them.AssetContainer can export/import meshes together with their userData, but it does not serialize arbitrary functions either.The serialization routine walks the scene graph and copies only properties that pass a JSON‑compatibility check. Since JavaScript functions are not JSON‑serializable, they are stripped out. Consequently, any behavior that relies on those functions must be recreated after the scene is loaded.
mesh.userData = { scriptId: 'moveForward', speed: 2.0 }.const json = scene.toJSON();SceneLoader.Append('', json, engine, function (newScene) { … });.userData.AssetContainer to export/import meshes and their userData, then reapply logic as in step 4.Are you trying to persist closures that capture external variables? If yes, the simple userData flag approach will not work; you would need to externalize those captured values or use a sandboxed code‑reconstruction strategy, which changes the recommendation.
Use comments to ask for clarification. Post a solution as an answer.
4,300 reputation · 04 Dec 2023, 16:37 UTC
Babylon.js’ scene.serialize() only writes the visual tree. To restore behaviour you usually store a scriptURL (or module name) in mesh.userData and let a scene.customSerialization callback add that field to the exported JSON:
mesh.userData = { scriptURL: 'scripts/move.js' };
scene.customSerialization = (scene) => {
const data = {};
scene.meshes.forEach(m => {
if (m.userData?.scriptURL) {
data[m.id] = m.userData.scriptURL;
}
});
return data;
};
After loading with SceneLoader.loadAsync, iterate the returned scene and import each module, then re‑attach the logic:
const json = await SceneLoader.loadAsync(...);
Object.entries(json.customSerialization).forEach(async ([id, url]) => {
const mod = await import(url);
const mesh = json.scene.meshes.find(m => m.id === id);
mod.apply(mesh);
});
Note: customSerialization runs only during export; it does not execute automatically on load, so the re‑hydration step must be coded explicitly.