amethlex

How to Stop and Restart engine

Recommended Posts

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/Mesh.prototype.dispose
  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

  72 | if (this.mesh) {
> 73 |   this.mesh.dispose();
  74 | }
  75 | 

Share this post


Link to post
Share on other sites

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! :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.