Destroy a scene and re-instantiate it

Hello there,
As usual I think I’m missing something.

Scenario:
I have a scene Foo that starts another scene Bar.

In Foo:

...
this.scene.start("Bar"); 
...

Then after a while, Bar ends and Foo removes it.

In Foo:

...
this.scene.remove("Bar"); 
...

then I want that Foo starts Bar again, but with another instance.

In Foo:

...
this.scene.restart();
...

The result is a blank screen… This is weird!

So I tried another way, instead of “remove” I used “stop”

In Foo:

...
this.scene.stop("Bar"); 
this.scene.restart(); // and then restarted Foo as above
...

This works but the constructor of the class Bar is not invoked so the instance is the previous one and I need to clean all my data structure in Bar manually.
It’s not a big problem because usually I reinizialize the datatypes that I need in Bar but I think that it would be better to restart with a brand new one instance.

Any hints?
Thanks in advance

If you remove a scene it’s gone completely. You have to add a new one:

const barScene = this.scene.get('Bar');

barScene.events.once('destroy', function () {
  this.scene.add('Bar', Bar, true);
}, this);

Avoid restarting Foo because that will get more confusing.

The usual way to do this (without removing) is

this.scene.launch('Bar');
// …
this.scene.stop('Bar');
// & repeat …
1 Like

Hi samme,
As usual, thanks a lot.
It worked, I managed to remove the Bar scene and then to re-add it when the destroy event is triggered.
In this way I think all is much more clean because the Bar scene (in my game) is really a big one.

For completeness in my game I have (right now) a BootScene whose purpose is to instantiate the game scene (MazeScene) and the interface scene (InterfaceScene).
For this reason I leave here how I managed the “destroy” that can occur both from MazeScene or InterfaceScene.
The “destroy” event is triggered by invoking the method “dispose” on each scene so when one scene is destroyed I need to trigger the dispose on the other one.
Then the level increases, a new maze is created and the MazeScene and InterfaceScene are started again.

import Levels from "../levels/Levels";
import Maze from "../maze/Maze";
import InterfaceScene from "./InterfaceScene";
import MazeScene from "./MazeScene";

export default class BootScene extends Phaser.Scene {
  constructor() {
    super({ key: "BootScene" });
    this.destroyScenesCounter = 0;
  }

  create() {
    this.createMaze();
  }

  createMaze() {
    // Creates the maze 
    this.maze = new Maze(Levels.getLevel(), this.mazeReady.bind(this));
    this.maze.init();
  }

  mazeReady(e) {
    // The maze was created successfully, scenes can be added and started
    this.startScenes();
  }

  startScenes() {
    // Add the scenes (the scenes are not in the config)
    this.scene.add('InterfaceScene', InterfaceScene, false);
    this.scene.add('MazeScene', MazeScene, false);

    // Start the scenes
    this.scene.start("InterfaceScene")
    this.scene.start("MazeScene", this.maze.json)

    // Set the listener on MazeScene and when triggered try to dispose also InterfaceScene
    this.mazeScene = this.scene.get("MazeScene")
    this.mazeScene.events.once("destroy", () => {
      this.mazeSceneEnded();
      if (this.interfaceScene) {
        this.interfaceScene.dispose();
      }
    });

    // Set the listener on InterfaceScene and when triggered try to dispose also MazeScene
    this.interfaceScene = this.scene.get("InterfaceScene")
    this.interfaceScene.events.once("destroy", () => {
      this.interfaceSceneEnded();
      if (this.mazeScene) {
        this.mazeScene.dispose();
      }
    });
  }

  
  mazeSceneEnded() {
    // The scene was disposed successfully
    this.destroyScenesCounter++;
    this.mazeScene = null;
    if (this.destroyScenesCounter === 2) {
      this.levelEnded();
    }
  }
  
  interfaceSceneEnded() {
    // The scene was disposed successfully
    this.destroyScenesCounter++;
    this.interfaceScene = null;
    if (this.destroyScenesCounter === 2) {
      this.levelEnded();
    }
  }
  levelEnded() {
    // Both the scenes were destroyed successfully
    this.destroyScenesCounter = 0;

    // Increase the level of the game (this part is still to do)
    Levels.current++;
    if (Levels.current === Levels.LEVELS.length) { 
      Levels.current = 0;
    }

    // Recreates the new maze
    this.createMaze();
  }
}