Change scene problem

Hi,
I have a problem when changing scenes in my VR application, as it freezes as soon it enters the new scene.
In my computer it always works well, but with the headset it is impossible to make it work.

The code i am using is very simple:

var c = pc.createScript('c');

c.attributes.add('sceneT', { type: 'string' });

c.prototype.initialize = function () {
    this.entity.button.once('click', function () {
        loadScene(this.sceneT, { hierarchy: true, settings: true });  
    }, this);
};

which calls this function:

function loadScene(sceneName, options, callback, scope) {
    var app = pc.Application.getApplication();
    var scene = app.scenes.find(sceneName);

    if (scene) {
        var wasSceneLoaded = scene.loaded;

        app.scenes.loadSceneData(scene, function(err, scene) {
            if (err) {
                if (callback) {
                    callback.call(scope, err);
                }
            } else {
                var sceneParent = null;

                // Destroy all the entities on the app.root to completely remove 
                // the existing scenes
                var rootChildren = app.root.children;
                while(rootChildren.length > 0) {
                    rootChildren[0].destroy();
                }

                // As we've already loaded the scene data, the callbacks for these
                // functions will be called immediately
                if (options.settings) {
                    app.scenes.loadSceneSettings(scene, function (err) {
                        if (err && callback) {
                            callback.call(scope, err);
                        }
                    });
                }

                if (options.hierarchy) {
                    app.scenes.loadSceneHierarchy(scene, function (err, parent) {
                        if (err) {
                            if (callback) {
                                callback(err);
                            }
                        } else {
                            sceneParent = parent;
                        }
                    });
                }

                if (!wasSceneLoaded) {
                    app.scenes.unloadSceneData(scene);
                }

                if (callback) {
                    callback.call(scope, null, sceneParent);
                }
            }
        });
    } else {
        if (callback) {
            callback.call(scope, "Scene not found: " + sceneName);
        }
    }
}

I cannot even guess what could be happening
Thanks for your help

Hello practicas_imas! Could you send me a link to your project?
Also, just to confirm, it only freezes during testing on your headset, correct?

1 Like

Yes, it only freezes with the headset
I have sent you the link through private message (i have to maintain it private until mid september, then i will edit so it can be of help for others)
Thanks for helping!

Hello again practicas_imas! I’ve examined you project and determined the cause of the issue. When you switch scenes, you are destroying the camera that is being targeted as the controller by the VR device. The new scene you load also has a camera, but this does not make the VR device automatically retarget the new camera as its controller.

If you wish to change scenes without triggering this you will need to place the camera in a separate scene and load other scenes additively on top of that.

The basic workflow is as follows:

  • Start game at an empty scene with just the camera
  • Additively load your desired first scene on top of that
  • Whenever you wish to move to a new scene, unload the previous scene and additively load the next scene.

I understand this may seem a bit complex so I’ve went ahead and made an example project. Take a look at /scripts/scene-loading.

3 Likes

I have tried and it also seems not to work. It loads the first scene yes, but then it does not let me go into VR. You can click the VR button to dive in but nothing happens

That is strange; I could enter VR mode normally when I tested it. I’ll check again to be sure.

1 Like

Ok, it was my headset mistake. It was doing weird stuff so i turned off
Now it seems that it does let me dive into VR, but the image is frozen. When you turn your head it displays the same that was in front of the camera when first rendering the new scene.

I’m able to jump into VR mode just fine, as well as move around with the headset on the example project.

Are you starting/launching from the Bootstrap scene?

Yes i am.
Can you try in the link i provided to you? The scene ‘‘test’’. It will load a room where is a table/screen with pictures, clicking on them will teleport to other rooms. When doing this it freezes.
If it works in my project can you tell me what device are you using? I do not think it is the device but who knows…

There is a problem. Some elements persists when changing the scene. So it is more like mixing scenes. Do you know any way of fixing this?

Hello practicas,

Regarding which project I tested it on, I meant the example project - apologies if that was unclear.

Regarding the ‘mixing’ of scenes, PlayCanvas’ loading and unloading of scenes is basically just spawning and destroying the scene hierarchies. You might be loading (spawning the scene’s hierarchy) but forgetting to unload the previous scene (delete its hierarchy root).

Deleting the hierarchy root is just like deleting any other object with destroy(). It should be noted that all scene roots are placed as children to pc.app.root, and the last loaded scene is always the furthest child in the hierarchy. You could, as a simple solution, delete pc.app.root.children[childrenLenght - 1] to clear the previous scene.

Let me know if you encounter any more issues!

2 Likes

Yes, i am doing that just before loading the new scene:
function unloadLastScene() { var app = pc.Application.getApplication(); app.root.children[app.root.children.length - 1].destroy(); }
but happens anyway

You want to unload the penultimate scene after loading the new scene. app.root.children[app.root.children.length - 1].destroy() effectively destroys the penultimate child of app.root. If you call this before loading the new scene you may destroy things you wish to keep.

The example project shows the workflow you’re looking for, and I’ve updated it for further clarity.

1 Like

Yeah, was doing that in the wrong order. But still those strange things happen, as the following duplicated levers:

Hey practicas,

Could you lay out exactly what steps you’re taking; what scene you’re starting from, what button you’re clicking, what new scene you’re loading and what script you’re using in your project to drive the scene loading and unloading?

  1. It is loading scene ‘‘test’’, which additively loads scene “DemoScene” they way you do in the example project. That first load works ok i guess.

  2. Then in that room you are now there is a screen in the middle, which has some pictures with names “sala 1”, “sala 2” … if you click on them that should change the scene you are in.

The problem is that it mixes both, and usually it just freezes. For this change i am following the steps of your example project too

loadSceneAdditive(this.sceneName, { hierarchy: true, settings: true });  ///if VR we load additively
unloadLastScene();

this unload() is the same as your unloadPreviousScene function

I guess is something about the cameras. I have seen you just have one in the first load, and i have one for each scene, but doing the same you do (having only one at first scene) i do not know why i cannot make it work. Can you help me find why? Is the only thing that lasts to end the work and it is really driving me mad

Hello @practicas_imas,

Yes, you want for there to only be one camera at a time, and for that camera not to be destroyed when you load/change scenes. The example project has a camera in the initial scene. I then load other scenes on top, but notice how I never delete the original scene containing the camera. For your project, here’s what I’d recommend you do:

  1. Create a ‘Bootstrap’ scene, containing only your camera, VR controllers, and a script that additively loads your desired scene - ‘Demo Scene’, for example.
  2. Start the game from your ‘Bootstrap’ scene. Your script should additively load your desired scene right away.
  3. When you wish to load another scene, additively load it, then unload ‘Demo Scene’, but do not unload the ‘Bootstrap’ scene containing your camera and VR controllers.

Make sure that there are no cameras other than the one in the Bootstrap scene. Delete any other cameras you encounter.

2 Likes

ok, i made it work at last. But there is a problem: sometimes is like it is not deleting some of the scenes and finally after changing the scenes 10 times or so it finally crashes.

This is my project build in top of yours: PlayCanvas | HTML5 Game Engine

The problem should be when deleting the last scene, but i do not find where the problem is
Could you help me please?

Hey @practicas_imas,

I’ve checked your project, and haven’t noticed any issues, nor have I been able to replicate the crash. Scenes are getting deleted properly, there seem to be no memory or performance issues, so I’m not sure what could be causing this. To help you any further I would need console logs from the crash on your device. You would need to set up Chrome remote Dev Tools and send me the log when it crashes.