Teleportation controls to bind on only one controller

I have been using VRExperienceHelper.enableTeleportation() to allow me to move around the scene and it is very useful. However, when I run this method, it enables teleportation for both controllers which conflicts with my own controls. Is there a way to enable teleportation on a single webVRController instead of both?

I haven’t found any options that allow it.

https://doc.babylonjs.com/api/classes/babylon.vrexperiencehelper#enableteleportation

Hi the_russell,

Welcome to Babylon! Just as a heads-up, I believe the VRExperienceHelper and related classes are no longer the recommended way to do virtual reality with Babylon. Those classes were built around WebVR, which is an older API that the industry has since gravitated away from. The most active development is now for WebXR, so probably the best teleportation mechanism to use would be the WebXR teleportation system.

Skimming over that documentation and the source code behind it, it looks like the current behavior is to attach all controllers to the teleportation system, as you described in your original post. @RaananW, is there currently a mechanism to do this?

If not and (because speculating is fun :smiley:) if you just need to work around the issue quickly/temporarily, I can think of two other things you might try.

  1. You could try passing an input subset instead of the full XR input object when calling featuresManager.enableFeature, as shown in the documentation linked above. This might be tricky–I’m not very familiar with the XR input object, so I can’t be sure just how much of a hack “spoofing” it would be–but it’s the cleanest way that jumps out at me in the current implementation to make sure that the teleportation system doesn’t attach to one of your controllers.
  2. Alternatively, you could try hacking around the problem (especially if you’re programming in JavaScript) by manually calling the private _detachController method to make the teleportation system forget about one of your controllers after it’s already attached to it. This is even more of a hack than the first idea, but it’s probably the fastest and easiest option to try.
1 Like

What he said ^

:slight_smile:

As you asked about VR - no, it is not possible. As WebVR is deprecated, we will not be adding new features there, but if you want it enabled in WebXR, please submit a ticket and I will implement it when I have the time.

About the two options - 1st one will sadly not work (as the input is the one firing the events).
Option 2 is a great way to do that. If you don’t want to deal with private methods (because typescript will complain a LOT), you can do something else (thou I haven’t tried it). Attach an observer to the input.onControllerAddedObservable, but add it to be first (the 3rd variable in the add function). Then, if it is the hand you want to not have teleportation on, set state.skipNextObservers to be true. Something like this:

xrInput.onControllerAddedObservable.add((controller, state) => { if (controller.handness === 'left') {
  state.skipNextObservers = true;
}, undefined, true);

This might have a few side effects (if you have other observers registered that are actually needed). so make sure to remove this observer after it was triggered.

The simplest solution, however, if to make it right and implement this feature :slight_smile:

1 Like

Thanks guys!! Any advice on how to get WebXRExperienceHelper loaded? I am including my Babylon files in my HTML, but WebXRExperienceHelper is not defined. I don’t know if this is because I need to include the WebXRExperienceHelper source code or something related to async. None of the Playground examples will run for me when I download them. I am not using TypeScript.

I actually just fixed the playground issue, hard-refresh the playground and try downloading again.

Try this, it is a nice example of how teleportation works - Babylon.js Playground