amethlex Posted December 12, 2017 Share Posted December 12, 2017 Hi All, I'm developing an React.js APP which consists of multiple pages. One of pages contains canvas, scene and of course, engine while other pages don't. Naturally, I need to dispose scene and stop engine when I am going to leave this page while init the scene and runRenderLoop when I re-eneter this page. The related code is as follows. class Scene { constructor() { this.canvas = null; this.engine = null; this.scene = null; this.obstacles = null; } init(canvas) { this.canvas = canvas; this.engine = new BABYLON.Engine(canvas, true); this.scene = new BABYLON.Scene(this.engine); this.scene.clearColor = new BABYLON.Color3.Black(); this.obstacles = new Obstacles(this.scene); } run() { window.addEventListener("resize", () => { this.engine.resize(); }); this.engine.runRenderLoop(() => { STORE.updateFPS(String(this.engine.getFps().toFixed())); this.scene.render(); }); } stop() { STORE.toggleSceneActive(false); window.removeEventListener("resize", () => { this.engine.resize(); }); this.engine.stopRenderLoop(); this.scene.dispose(); this.engine.dispose(); } } export default class Canvas extends React.Component { render() { return ( <canvas className="main-canvas" ref={(canvas) => { if (canvas === null) { // React will call the `ref` callback when the // component is being umounted. SCENE.stop(); return; } SCENE.init(canvas); SCENE.run(); }}> </canvas> ); } } The problem is that when I go back to this page and try to dispose the mesh of obstacle to redraw, which is BABYLON.MeshBuilder.ExtrudePolygon(). It reports error: Does anyone have any idea? What's wrong with my operations? TypeError: engine is null ./node_modules/babylonjs/dist/preview release/babylon.max.js/AbstractMesh.prototype.dispose src/visualization/browser/node_modules/babylonjs/dist/preview release/babylon.max.js:13927 13924 | this._occlusionQuery = null; 13925 | } 13926 | // Engine > 13927 | engine.wipeCaches(); 13928 | // Remove from scene 13929 | this.getScene().removeMesh(this); 13930 | if (!doNotRecurse) { ./node_modules/babylonjs/dist/preview release/babylon.max.js/Mesh.prototype.dispose src/visualization/browser/node_modules/babylonjs/dist/preview release/babylon.max.js:22773 22770 | highlightLayer.removeExcludedMesh(this); 22771 | } 22772 | } > 22773 | _super.prototype.dispose.call(this, doNotRecurse); 22774 | }; 22775 | /** 22776 | * Modifies the mesh geometry according to a displacement map. updateState src/visualization/browser/src/scene/obstacle.js:73 72 | if (this.mesh) { > 73 | this.mesh.dispose(); 74 | } 75 | Quote Link to comment Share on other sites More sharing options...
brianzinn Posted December 12, 2017 Share Posted December 12, 2017 hi, Instead of relying on the ref={ () => ...} you could wire into the React lifecycle event to tear down your scene/engine in componentWillUnmount(). I'm wiring up the canvas in the componentDidMount() event, as that will ensure that the canvas (via ref) is loaded:https://github.com/brianzinn/react-babylonJS/blob/master/src/Scene.tsx Looking at that code now I really feel like I should be calling engine.dispose() in componentWillUnmount()! It started as a proof of concept, but I use it a lot and switch between pages with and without BabylonJS scenes - so far no noticeable issues using that code. Also, are you maintaining the state in your store to re-init the scene? I'd like to hear more about what you're doing if that doesn't work! Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.