Switching between multiple scenes

I’m attempting a game with threeJS. For the time being, the 3D visuals is just a backdrop. When the player changes locations in-game, the backdrop needs to change as well.

How bad an idea is it to have multiple scenes prepped, and switch between them? I’ve already implemented it and is working as expected, but just wanted to know if it’s gonna eventually break or just whether it is bad practice.

1 Like

Depends on the complexity of the scenes - of the scenes aren’t too busy, you should be 100% fine keeping them in memory and just switching between them on the go.

2 Likes

You can also lazy load scenes using the import (…) statement. Scenes you don’t need yet won’t be part of the bundle.

1 Like

For one of my projects, I created a simple router to navigate to a scene. In the main app, I register each of the scenes like this

      app.router.add('/', () => { return new GalleryExample(app) })
      app.router.add('basic', () => { return new BasicExample(app) })
      app.router.add('geometry', () => { return new CustomGeometryExample(app) })

The Gallery has an image that lets me navigate to a scene

    this.router.navigateto('basic')

This gives the lazy loading the @drcmda mentioned. It works quite nice.

Every route/scene (context) has a dispose method to cleanup things like document event listeners.

import { EventDispatcher } from "three";

interface Route {
  [path: string]: () => any
}

export class UIRouter extends EventDispatcher<any> {
  constructor(public routes: Route = {}) {
    super()

    let context: any

    // The actual router, get the current URL and generate the corresponding template
    const router = () => {
      if (context) {
        context.dispose()
        this.dispatchEvent({ type: 'unload' })
      }

      const url = window.location.hash.slice(1) || "/";
      try {
        console.log('loading', url)
        this.dispatchEvent({ type: 'load' })
        context = routes[url]()
      } catch (error) {
        console.error(`Invalid route ${url}`)
      }
    };

    window.addEventListener('load', router);
    window.addEventListener('hashchange', router);
  }

  add(path: string, example: () => any) {
    this.routes[path] = example
  }

  navigateto(route: string) {
    window.location.href = '#' + route
  }
}

The full implement is here

Hope this helps

2 Likes