Help Problems restarting a scene. How to restart a scene correctly?..onReadyObservable does not work

Hello everyone I am trying to understand how to restart a scene, for that I have the following code example.

  var canvas: HTMLCanvasElement = document.getElementById("renderCanvas") as HTMLCanvasElement;;
var engine: BABYLON.Engine = new BABYLON.Engine(canvas, true);

function NewScene() {
    // This creates a basic Babylon Scene object (non-mesh)
    var scene = new BABYLON.Scene(engine);
    scene.debugLayer.show();
    
    console.log("¡¡INIT!!");
    
    // This creates and positions an arc rotate camera (non-mesh)
    var camera = new BABYLON.ArcRotateCamera("Camera", BABYLON.Tools.ToRadians(90), BABYLON.Tools.ToRadians(90), 5, new BABYLON.Vector3(0, 0, 0), scene);    
    camera.attachControl(canvas, false);

    // This creates a light, aiming 0,1,0 - to the sky (non-mesh)
    var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);

    // Default intensity is 1. Let's dim the light a small amount
    light.intensity = 0.7;

    //Observable to know when it starts,
    //does not work when calling function again
    scene.onReadyObservable.add(function (){
        console.log("init the scene ")
    })

    return scene;
};



//I create the new scene and save it in a variable
var iniciarEscena:BABYLON.Scene = NewScene();


//if i press click i make the variable
//call the function again
window.addEventListener("click", function () {
   iniciarEscena = NewScene();// I call it again in the variable
   console.log("reinicie la escnea")
});



//principal renderLoop
engine.runRenderLoop(function ()
{  
    iniciarEscena.render();
});

I mean, as you can see, what I do is press click and call the variable again.

and I have an observable to check when the scene starts
However it doesn’t work

How can I verify that the scene was restarted and started correctly?
I see strange things, I mean the scene restarts, but it does not show the messages by console when verifying that the scene was reloaded
IF I create a custom observable it doesn’t work either or it works 1 time only.

I’m guessing that you haven’t disposed the scene. Before creating a new scene, make sure you call scene.dispose() on the old scene.

Ok thank you very much, could you explain to me why this happens too … I mean when I restart the button disappears …
The issue is that when I restart if I have custom observables they stop working, I cannot understand well how to restart a scene.

Another problem that I see is that when using a button to restart many problems arise like this one that is seen below

var canvas: HTMLCanvasElement = document.getElementById(“renderCanvas”) as HTMLCanvasElement;;
var engine: BABYLON.Engine = new BABYLON.Engine(canvas, true);

function NewScene() {
    // This creates a basic Babylon Scene object (non-mesh)
    var scene = new BABYLON.Scene(engine);
    scene.enablePhysics(new BABYLON.Vector3(0,-9.8,0),new BABYLON.CannonJSPlugin());
    scene.debugLayer.show();
    button1 = new flappyBird().CrearBoton();
    console.log("¡¡INIT!!");
    
    // This creates and positions an arc rotate camera (non-mesh)
    var camera = new BABYLON.ArcRotateCamera("Camera", BABYLON.Tools.ToRadians(90), BABYLON.Tools.ToRadians(90), 5, new BABYLON.Vector3(1.5,8,0.10), scene);    
    camera.alpha = -0.60;
    camera.beta = 1.87;


    camera.attachControl(canvas, false);

    // This creates a light, aiming 0,1,0 - to the sky (non-mesh)
    var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);

    // Default intensity is 1. Let's dim the light a small amount
    light.intensity = 0.7;


    // Observable to know when it starts,
    // does not work when calling function again
    // scene.onReadyObservable.add(function (){
    //     console.log("init the scene ")
    // })

    return scene;
};

//I create the new scene and save it in a variable
var iniciarEscena:BABYLON.Scene = NewScene();

var button1:BABYLON.GUI.Button
button1.onPointerClickObservable.add(function()
{
    iniciarEscena.dispose();
    iniciarEscena = NewScene();// I call it again in the variable
    button1 = new flappyBird().CrearBoton();
})


//Observable to know when it starts,
//does not work when calling function again
iniciarEscena.onReadyObservable.add(function (){
    console.log("init the scene ")
})


//principal renderLoop
engine.runRenderLoop(function ()
{  
    iniciarEscena.render();
});

Can you try to put this in a playground or codepen?

Ok i do now.

Here I create a button and try to restart from the same scene, but that is not possible or I cannot find the way. I leave you a larger project, it would also be ideal if they made a video explaining the correct ways to restart a scene in babylon and give some examples using observers to check its operation.
https://playground.babylonjs.com/#C4R5RZ#2
flappy bird babylon forma 2.zip (1.4 MB)
This is how a reboot or scene change works in Godot, “look at the hierarchy”


The playground is expecting one scene and handles the render loop automatically. If you delete the scene, then you need to run the render loop manually.

https://playground.babylonjs.com/#C4R5RZ#4

ok and then what would it be like to restart the current scene?
The problem is that babylon doesn’t seem to have a function to easily reset the scene.

Disposing the scene removes all the objects in the scene. Call createScene again if you want to restart back to the original using code. If you save the scene to a Babylon file, you can reload it after disposing the current scene. I don’t know Godot, but I’m assuming it has some kind of saved scene associated with the project, so saving as a Babylon file and reloading will be closest to that.

And there is no function in babylon.jS that does that automatically?

Not currently.

Now I have another problem related to restarting and calling again using “dispose” that has been breaking my head for several days.
From the scene there is a personalized observer
Called “onReset” that observer sends the signal after pressing the button to the instantiated scene as follows.

The problem is that after making the scene available, it is no longer possible to restart it, it is like the observable is disconnected. Watch this video.



I think it would be best if you give us some examples in a video by youtubes…Thank you very much for the answers.

This is expected. Once the scene is destroyed, all the events, objects, etc. are also destroyed. You have to recall all of these functions to make sure they are hooked up again.

I made this code simplified showing that error and
I uploaded the example to the playground but it doesn’t work. In this example you can see the observable.
I mean what I do is that when pressing the button it sends the message using the observable to notify the instantiated scene that it has to restart, (“this is very similar to the Godot Engine signals”), the problem is that I don’t know how to return to call functions, can’t find the form, try “onReadyObservable” but it doesn’t work.
the message “I AM IN THE OBSERVABLE I WILL RESTART” can be seen by the console 1 only time

https://playground.babylonjs.com/#8SQ42U#3

You are trying to take a different engine’s architecture, and expect to have the exact same thing in Babylon. Just because some other engine has it, does not mean babylon has it. I am not saying it isn’t. It might be!! I am just saying that mentioning Godot or Unity on each post won’t help, as this is not Unity or Godot. This is the babylon.js forum. We do things differently, just like any other engine.

I don’t know how this works in Unity or Godot.

Now, about resetting a scene, since this is the big issue - Babylon has an engine object. the engine object renders scene(s). Each scene is on its own an object full ob other objects (such as observables, meshes, textures, buttons and so on). When disposing this scene, ALL of the associated resources will be disposed with it - meshes, textures, buttons, babylon-defined observables, and the scene will no longer be able to render.
An engine renders the scene using a render loop. On each frame, the render-loop function is called, and this function has a call to render (a or the) scene. Outside of the playground, this is managed and controlled by you, the developer, and not by babylon.
If the way you want to reset a scene is by disposing the old one and recreating a new one, Kudus on that. Do it. But they way you are expecting it to work won’t work.

In the playground you created, on the main loop, you are - creating an engine, creating a scene, adding the observable call to the scene, and adding the render loop for the scene. Inside the observable you are disposing the scene (the scene that holds the observable), and create a new scene:

newScene.onReload.add(function(reload) {
    //iniciarEscena.dispose();
    console.log("I AM IN THE OBSERVABLE I WILL RESTART")
    newScene.dispose();
    newScene = NewScene();// I call it again in the variable
})

But you are never adding the observer again, so this will obviously only work one single time. You are adding an observer to an observable in an object that is (after being disposed) no longer used.

Want a reset game function? create one. a function that takes an old scene, and returns a new scene. This reset function should take care of everything needed - making sure the engine’s render loop is referencing the right scene, adding observers, initializing meshes, everything. And then call THIS function. Keep everything in this function, don’t use any global objects or variables. everything is a part of a scene that is being created.

And how would you do all that because it’s practically having to invent a restart engine? … I would like to see a code example. I have been trying to do it for more than 5 days. If all engines come with tools to easily restart scenes, why won’t babylonJS have them? … If nobody mentions it, it will never exist. The subject of making comparisons has nothing to do with Godot or the unit, but with the concepts of the tools to facilitate the development of a game … I usually use several Game Engine so I have an overview of the tools.
I thank you very much for your council, at least you made it clear to me that the scene is completely destroyed, I will have to work on what you told me … Thank you.

Personally I would never destroy the scene. I see no reason to do that.

The meshes array can be emptied, the camera’s position can be re-set back to the original state, the different variables can be set back to their original value. I don’t see a reason to dispose the scene entirely.

It all depends on your architecture and what you need. You are the one responsible for it, and code examples will only provide you with a solution that you won’t be able to continue developing. If you do it and make it work, you will be able to continue developing it. If you are looking for an engine.resetScene() function to be made for you - that will probably not happen…

Using the playground to try to do demo a restart brings added issues because of the overarching code that runs the playground code.

The issue here IMHO is that restarting is not a Babylon.js issue as such. It is a question of variable scope, logic and Javascript and just applying this thinking leads to this example. This is one way to achieve a restart.

Click green button to change the scene, red button to restart

github code

2 Likes

Ok, I understand, but it is 10 times more work and it is not about me, but about having tools to facilitate development, if I have to do everything from scratch it does not make sense … The advantage of babylon is that it is 100% web, Although I see that it fails in basic things like restarting a scene … ALL THE GAME ENGINES HAVE THIS TOOL … I will also continue experimenting to draw my own conclusions and try to implement everything you recommended to me to gain experience with the tool … Thanks for taking the time to answer me.