Trouble with adding a new scene

Hi Everyone,

I’m following the devlogs (Phaser 3 Dev Log #121: The second part of the huge Scenes tutorial and the new 3.7 Loader updates. - Phaser3 - Phaser) and I can’t seem to add a scene from within another scene. When I run the below code, the console.log(self.scene.get('handle')) line just logs ‘null’ and console.log(battle_scene) does seem to be logging a Scene. I’m a little lost here and would really appreciate if someone could point me in the right direction. Also, I’d appreciate if someone could show me how to create code blocks for this code. I don’t know how, sorry it’s just text.

var self = this;

eventsCenter.on("battleSceneStart", function (data) {
  //start a unique battle scene for the two playerIds in "data" which adds a new scene to the scenes list
  console.log(data);
  let key = { key: "handle" };
  let battle_scene = new Battle_Scene(key);
  self.scene.add("handle", battle_scene, true);
  console.log(battle_scene);
  console.log(self.scene.get("handle"));
});

The Battle_Scene class code is below.

class Battle_Scene extends Phaser.Scene {
  constructor(handle) {
    super(handle);
  }
  preload() {
    //Load sprites, maps, and images
  }
  create() {
    //Create reference to 'this' that can be used within other functions
    var self = this;
    console.log("battle_scene created and started");
  }
  update() {}
}

As an update, the code seems to work if I move the scene creation outside of the eventCenter callback, which is just defined as follows: const eventsCenter = new Phaser.Events.EventEmitter()

I can’t figure out why I can’t run the scene creation code code as part of an event callback…The following code works when it is not in a callback, but does not work when it is in a callback.

let key = {key: ‘handle’};
let battle_scene = new Battle_Scene(key);
self.scene.add(‘handle’, battle_scene, true);

update 2: I wondered if I was just missing something and maybe I was writing this code in a way that wouldn’t work in callbacks. I can confirm that the following code adds a new active scene to the scenes list.

this.input.keyboard.on('keyup-Z', function (pointer){
			let key = {key: 'handle'};
			let battle_scene = new Battle_Scene(key);
			self.scene.add('handle', battle_scene, true);
		});

So the problem really seems to be the fact that the code is in an event listener function. I tried swapping ‘self’ to ‘this’ and using an arrow function instead, but that still didn’t work. I would really like to understand why this is the case and if there is anything I can do to make it work. My game is multiplayer and when two players want to battle, they need to interact with each other (top down) then spin up a unique battle scene between the two of them (which I plan to remove from the scenes list when they leave).

During some phases of the game step, scene add operations are queued for the next step. That’s why you’re getting null immediately after scene.add(). But the scene is still getting added and started, or it should be.

Also, an alternative is to add the Battle_Scene class once at the start of the game and then start and stop it on demand.

1 Like

Hi @samme,

Thanks for your reply!
I tried putting the following line

console.log(this.scene.get('handle'))

in the update() function so it would continuously return ‘null’ until after the event, but even after the event runs it keeps returning ‘null’ so I don’t think it is getting added. Can you think of anything that would prevent it from being added and started?

Unfortunately, I think that adding the Battle_Scene early on and then stopping and starting it won’t work for my goal. What I eventually want to do is spin up a unique scene (‘minigame’) every time two players interact (it transitions from top down to a turn based game for those two players), then when they finish battling I was planning on removing that scene from the scene list.

You can try stepping through scene.add() in the debugger. It should either add the scene, queue it for adding, or throw an error.

Is it possible you’re removing the scene immediately?

I use phaser-plugin-scene-watcher/ for these problems.

1 Like

Hey @samme,

I’ve never used the debugger before. I’ll go try to learn how to use that.

Also, I’ll try that scene-watcher plugin. Looks really helpful!

Thanks for the suggestions! If either of these help me find the a way to solve this problem, I’ll come back and update.

I don’t think it’s possible I’m removing the scene immediately. I was planning to add and remove scenes dynamically as needed, but I haven’t written the remove portion of the code yet since I was just learning how to add new scenes from within other scenes.

1 Like

@samme, you rock! This has been super helpful.

It’s clear from your code pen that there is nothing inherently wrong with the code. However, when I tried it myself, it still did not work. I’m running this code as a HEADLESS phaser instance on a node.js server (just localhost for now), so I decided to run a test with this code on my client side using phaser.AUTO just to see if it would work and sure enough, just like in your code pen, it did!

Now I just need to narrow down if the issue is a Node.js issue, a HEADLESS phaser issue, or if there is somewhere in my server side code that is creating the issue.

I’m going to mark your code pen as the solution, because it clearly shows there is no information in the question that can explain the issue.

Do you have any advice for how to figure out if this is a Node.js issue, a phaser.HEADLESS issue, or something in my server side code that’s causing the problem?

@samme BTW, I used your Code Pen to change the type in the game config object back and forth between the following:

Phaser.HEADLESS

and

Phaser.AUTO

Interestingly enough, the scene did not run the following line (part of the Battle_Scene create() method) when Phaser.HEADLESS was in the config object, but it did work when Phaser.AUTO was in the config object.

console.log("battle_scene created and started");

I think that’s a Phaser bug. You can add

// BUGFIX
Phaser.Scenes.SceneManager.prototype.update = function (time, delta) {
  this.isProcessing = false;

  this.processQueue();

  this.isProcessing = true;

  //  Loop through the active scenes in reverse order
  for (var i = this.scenes.length - 1; i >= 0; i--) {
    var sys = this.scenes[i].sys;

    if (
      sys.settings.status > Phaser.Scenes.START &&
      sys.settings.status <= Phaser.Scenes.RUNNING
    ) {
      sys.step(time, delta);
    }
  }
};
1 Like

@samme, this is so cool! Thanks so much for your help. I wouldn’t have been able to figure this out on my own, I really appreciate the time you took to help me today.

1 Like