Jumping between scenes while in WebXR

Hi guys, Proud to be a Babyloner :slight_smile:

I Have a question about navigating between scene while being in the webXR in VR experience.

To switch scenes, i would have to run the following (pseudo) code:

oldScene.xrHelper.baseExperience.exitXRAsync();
newScene.xrHelper.baseExperience.enterXRAsync("immersive-vr", "local-floor");

The problem is that the user experiencing a jump out of the XR session (as the code instructs) back to the browser and after a short while, entering to the XR back again.
I feel that this is a bad UX specially in a scenario when a lot of scene navigation is presented.

Any other way it can be done without the jumping out back to the browser and then jumping in to the webXR ?

thanks.

1 Like

As I think, @JCPalmer should to know how to do this correct =)

Also,
While rendering after the navigation a new scene with the same engine and the same canvas, i get a warning:

Can’t perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.

Do I need to do additional operations before starting a new scene?

cc @RaananW our XR guru

1 Like

Oh, interesting scenario!

There are a few ways to achieve it cleanly. The one I would personally choose is to switch to a different link while using the sessiongranted event which is already integrated in the default xr experience. The idea is this - every scene has its own URL. Switching between those 2 URLs will move the session to the new URL (and with it to the new scene) and the user will have a seamless experience.

If you want to move from one scene to the other in a single experience (like you are trying to do here) you will need to block the rendering while the session starts again.

Another way (which I have never tested TBH) is to implement the XR pipeline yourself using the babylon classes and move those classes from one scene to the other. It won’t be trivial, but more than possible. The WebXRSessionManager is your main entry point - the scene defined there is passed to all other modules. If you dispose all other modules apart from the Session Manager you will still have a running session with a new scene.

2 Likes

@Dok11, thanks for the ping. I have been heads down recently changing over lower level systems / mesh classes getting ready for multi-scene within the same engine instance, same as this topic. While i am a week or more behind here, but think there are a couple of things that go along with this.


First, a reminder that someone might want to do this in Babylon Native (it could happen). It may be that the desired goal here, may end up being implemented in Native by force. That is not a problem, nor is it a problem if there will be some other difference in the mechanism. Knowing that there will be a difference, Now though, would be nice to know for code organization.


Visual & Audio / transitions are obviously going to make the change over more graceful. I’ll leave the visual part up to “you can do whatever you can do on both sides”, but the audio context is another matter. Clearly having an audio buffer started prior to the change over and part of an transition animation is highly desire-able.

I use WebAudioFonts for stuff, so I could just do this outside of engine’s knowledge. But Audio Context is at the Engine level, so there should also be an option for starting a BABYLON.Sound completely independent of a scene, right?

I also notice that there is an option to pass a Web Audio Context in the Scene constructor, which is not really documented. What it is for & should that be utilized for scene switching?

Well still not actively looking at this, but a little IDE code completion “searching” shows that WebXRSessionManager has an isNative member. Probably need to do a complete read of that class.

@RaananW, your option 3 of replacing the scene right underneath an existing session seems best by a wide margin:

  • Synchronous. The code snippet by @lior3790 is 2 async calls. For production worthy code, you cannot do that. They must be nested. Beyond that there are a bunch of other things which need switched out / handled like render loop starting / stopping & canvas to scene attaching / detaching. If you wished to run on either a device or desktop, you always need to do the non-XR stuff. Inline switching seems less of a kluge to integrate.

  • I cannot imagine any other way that depends on dropping an old session & creating a new one being faster than this. That lightens the lift required for any transition process.

I don’t mind looking at a “moveXRToScene” function to switch scenes. I can create an issue for that, but sadly my backlog is, as always, rather long :slight_smile:

1 Like

I’ll try doing it outside of the framework, when I actually get to that point, rather than a direct function in SessionManager. Subclassing is my cheap way of developing for the framework without actually doing it yet, but not going work here. Will just hack any privates or just not write in Typescript.