Inspector not displayed on multiple scene

I am building an application with different “state”, and each state contains a scene. The main engine displays the current state :

this._engine.runRenderLoop((): void => {
    this.currentState.render();   // = currentState.scene.render()
});

When the state changes, the previous scene is “disposed”.

I though I could enable the Inspector in all scenes, by adding this piece of code in my abstract state :

this._scene.debugLayer.show({
    showInspector: true,
    embedMode: true,
});

I guarantee that this code is called each time I change the state, but it does nothing excepted for the first state. The Inspector is only showing on the first loaded state (= scene) and disappears as soon as the state change.

In the HTML, for the first state/scene, I see the inspector <div> embedding the rendering <canvas>.
For the second scene, I see the <canvas> alone as define in the HTML, without any div.

I saw this answer but calling this method as no effect : scene.debugLayer.setAsActiveScene();
Using a setTimeout with 0ms does not change anything either.

Any suggestion ?

Hello! You should be able to just call hide and show, like in this example: quick-demos/switch-scenes-inspector.html at 1e5d12016065d3ad5761b2c496fcf9361e7a3632 · carolhmj/quick-demos · GitHub

Can you share your code so we can have a better look?

Hi, I already hide and show the inspector as you suggest :

  onEnterState(): void {
    this._scene.debugLayer.show({
      showInspector: true,
      embedMode: true,
    });
  }

  onExitState(): void {
    this._scene.debugLayer.hide();
  }

I think your example works because you do not call scene.dispose(). In that case it works as expected in my code also, the Inspector is always visible. But as soon as I dispose an old scene, the Inspector is not able to show anymore on new scene (I did not notice this behavior when I posted the initial question maybe I should update it).

I’m still able to normally show the inspector even when disposing and recreating: quick-demos/switch-scenes-inspector.html at acf24178fcae63cb8151275b5703cb7348d48e58 · carolhmj/quick-demos · GitHub

Are you sure you’re calling hide before the scene is disposed?

Yes I am sure about that, I even use a setTimeout to call the dispose later. But I just discovered a bigger problem, maybe related :

  • I create a “State”, containing a dedicated scene (created with new Scene(engine))
  • Everything is ok, the single state is rendered (so its scene is rendered)
  • Then, I just add in my state constructor a simple new line : new Scene(engine) then It becomes the current displayed scene ! (or at least, the initial scene attached to the state is not displayed anymore, instead I have a clean purple screen).

It’s look like Babylon considers the active scene as the last created one, ignoring the rendering loop engine.runRenderLoop which continue to render the initial scene.
But now I think about it, it is even not possible since there is no camera attached to the new created scene.

This behavior looks like a bug, I will try to create a code demo for that.

Yep a code demo will help greatly.

If I use this code to create the scene ‘inside my state’, the initial scene attached to my state is rendered, as expected :

    setTimeout(() => {
      new Scene(engine);
    }, 0);

For better understanding of the “why” this situation : I have a “loading state” displayed with a dedicated scene (progress bar…), and inside this state I am creating another scene. I have to use a setTimeout, I don’t know why.

It’s still better to see the full code please.

The two problems are reproduced in this repository :

You have to click “New game” to change state, you will notice the inspector disappears if we dispose the previous scene.

Thanks for the code! I can see the problem happens when the previous scene’s dispose is called after the inspector is in a new scene. I talked with @RaananW who told me the debugLayer approach has some issues, and recommended using Inspector.Show instead. And I tested in your example, using Inspector works well! You only need to import the class:

image

And call it instead:
image

1 Like

in es modules scenarios :slight_smile:

(Flying away)

Thank you !

There is still this mystery, I think this has a technical explanation but it looks strange to have to create multiple scenes like this just to not break the current rendered scene.

Oh, I hadn’t looked at that part of the code. I see that you have a BaseState whose constructor creates a Scene:
image

and a LoadGame state which inherits from BaseState and is also creating a Scene on its constructor:
image

This is not necessary, your BaseState class already has a scene. If you remove the new Scenes from LoadGameState it works fine :slight_smile:

Yes of course but creating a new scene is my use case : the loading state is a scene, displayed during an amount of time, and during this time I want to create another scene :slightly_smiling_face:, for the next state.

You want to create a new scene for your game? In that case, you shouldn’t create it on the LoadingScreen anyway, you should send a signal so that your App creates it and pushes on the stack. Otherwise your state management will get all messed up :slight_smile:

I like the idea to have a simple state system where everything is state : the app become just a simple state machine. The loading state role is exactly to prepare the game state.

But whatever, we could probably design things differently, it would not change the problem : I think we cannot create 2 scenes in the same Javascript loop. But… I am not able to reproduce it on a playground so maybe… the truth is out there. :alien:

You can create however many scenes you want, but your state management system has to deal with it appropriately. :slight_smile:

I actually consider that I am doing things correctly :grinning:

The simple fact of calling new Scene(engine) change the current rendered scene, which is not an expected behaviour, the main engine loop pointing to another scene.

You can check that behavior in the code repository I previously given.

But anyway, the workaround is easy (setTimeout 0), this topic is solved and deals about something else, you guys have already given much time and I thank you very much for that, do not waste time on this :slightly_smiling_face: