WebXR Movement
Movement Module
The movement feature allows movement in the scene with controllers. It is separate from the teleportation module and is not designed to be used at the same time.
In order to enable this feature you must first ensure that teleportation is not switched on.
Teleportation can be disabled in the default XR experience:
const xr = await scene.createDefaultXRExperienceAsync({ disableTeleportation: true,});You can also disable teleportation manually before enabling the movement feature.
import { WebXRFeatureName } from "@babylonjs/core/XR/webXRFeaturesManager";const featureManager = xrHelper.baseExperience.featuresManager;featureManager.disableFeature(WebXRFeatureName.TELEPORTATION);The movement feature enables the camera's position to be changed with the controllers. Default configuration (can be changed in the options below):
- Left controller - rotate counterclockwise or clockwise
- Right controller - move forward/backward/left/right
import { WebXRFeatureName } from "@babylonjs/core/XR/webXRFeaturesManager";const featureManager = xrHelper.baseExperience.featuresManager;featureManager.enableFeature(WebXRFeatureName.MOVEMENT, "latest", { xrInput: xrHelper.input,});It is also possible to use the controller to set the movement direction. To do that, you need to disable the head-direction settings. You can optionally define which hand will control the rotation:
import { WebXRFeatureName } from "@babylonjs/core/XR/webXRFeaturesManager";const featureManager = xrHelper.baseExperience.featuresManager;const movementFeature = featureManager.enableFeature(WebXRFeatureName.MOVEMENT, "latest", { xrInput: xr.input, // add options here movementOrientationFollowsViewerPose: false, // default true movementOrientationFollowsController: true, // enable controller direction orientationPreferredHandedness: "left", // the preferred hand for rotation. Defaults to right. If hand is not found it will use the first found controller.});Movement Configuration Options
The current options for the plugin can always be found in the WebXR movement feature source code. Most of them are explained here.
One important option is movementOrientationFollowsViewerPose, which defaults to true. When configured to false, the forward direction will not adjust to the viewer pose, but only to the controller rotation. This can be useful for experiences where the viewer pose should not affect movement direction. For example, if you are moving forward and look left, you should not drift left but continue straight. You can try this in the playground above by changing the option.
The controllers themselves can be configured differently. For example, if you want to swap which hand controls rotation and which controls movement, override the customRegistrationConfigurations array. The feature handles movement and rotation state automatically and ignores them when rotation (rotationEnabled) or movement (movementEnabled) is not enabled. Speed is controlled by rotationSpeed and movementSpeed.
This swaps the handedness of the default configuration while maintaining the feature sensitivity thresholds:
import { WebXRControllerComponent } from "@babylonjs/core/XR/motionController/webXRControllerComponent";import { WebXRFeatureName } from "@babylonjs/core/XR/webXRFeaturesManager";const swappedHandednessConfiguration = [ { allowedComponentTypes: [WebXRControllerComponent.THUMBSTICK_TYPE, WebXRControllerComponent.TOUCHPAD_TYPE], forceHandedness: "right", axisChangedHandler: (axes, movementState, featureContext, xrInput) => { movementState.rotateX = Math.abs(axes.x) > featureContext.rotationThreshold ? axes.x : 0; movementState.rotateY = Math.abs(axes.y) > featureContext.rotationThreshold ? axes.y : 0; }, }, { allowedComponentTypes: [WebXRControllerComponent.THUMBSTICK_TYPE, WebXRControllerComponent.TOUCHPAD_TYPE], forceHandedness: "left", axisChangedHandler: (axes, movementState, featureContext, xrInput) => { movementState.moveX = Math.abs(axes.x) > featureContext.movementThreshold ? axes.x : 0; movementState.moveY = Math.abs(axes.y) > featureContext.movementThreshold ? axes.y : 0; }, },];const featureManager = xrHelper.baseExperience.featuresManager;featureManager.enableFeature(WebXRFeatureName.MOVEMENT, "latest", { xrInput: xrHelper.input, customRegistrationConfigurations: swappedHandednessConfiguration,});Other useful options are to change movement and rotation speed and to enable/disable movement (movementEnabled) and rotation (rotationEnabled), but these ones are also available on the feature itself to change at runtime. The threshold options determine the sensitivity when the input is accepted - the default is 0.25, which prevents accidental movements and jittering.
Walking Locomotion
WebXRWalkingLocomition is an experimental Babylon.js capability which
enables users to traverse VR spaces by "walking in place."
import { TransformNode } from "@babylonjs/core/Meshes/transformNode";import { WebXRFeatureName } from "@babylonjs/core/XR/webXRFeaturesManager";scene.createDefaultXRExperienceAsync({ disableTeleportation: true }).then((xr) => { const xrRoot = new TransformNode("xrRoot", scene); xr.baseExperience.camera.parent = xrRoot; xr.baseExperience.featuresManager.enableFeature(WebXRFeatureName.WALKING_LOCOMOTION, "latest", { locomotionTarget: xrRoot });});While it is highly recommended to move the WebXRCamera's parent
node in order to avoid conflating virtual positional data with XR
sensory readings, it is also possible to move the WebXRCamera
itself.
import { WebXRFeatureName } from "@babylonjs/core/XR/webXRFeaturesManager";scene.createDefaultXRExperienceAsync({ disableTeleportation: true }).then((xr) => { xr.baseExperience.featuresManager.enableFeature(WebXRFeatureName.WALKING_LOCOMOTION, "latest", { locomotionTarget: xr.baseExperience.camera.parent });});To move, simply face in the direction you want to go and "walk in place," lifting and replacing each foot in turn much as you would if you were actually walking forward. This is a control technique and is not expected to work "magically"; it may take a small amount of practice to perform a motion that the system recognizes as walking.
Under the hood, what the XR system is actually reacting to is the user's
head motion, specifically the characteristic back-and-forth "rocking"
motion traced by most people's heads when walking in place (or, for
example, on a treadmill). Because of this, walking-in-place motions which
keep the head stationary, or which cause the head to move erratically,
will not be recognized as "walking" by the WebXRWalkingLocomotion
feature. However, once a recognizable motion is performed, it should be
very easy and comfortable to replicate. Walking detection of a recognizable
motion should also be resilient to head orientation; because walking is
recognized from the movement of the head (at a guesstimated "nape of the
neck" position, which remains relatively stationary as the head rotates),
looking around while performing a recognizable "walking in place" motion
will not disrupt the locomotion feature.
When to Use This Feature
WebXRWalkingLocomotion is a form of continuous traversal, similar to
walking around in real life and distinct from discontinuous traversal
alternatives such as teleportation. The most common example of continuous
traversal in VR, as in other forms of interactive 3D, is controller-based
and typically leverages a thumbstick to sort of "slide" the user around
the world in a continuous manner. Many users find this "sliding" effect
to be uncomfortable in VR, and for this reason teleportation is often
chosen as the default traversal alternative in VR applications.
However, there are times when teleportation and other discontinuous
traversal techniques are unsuitable, and in such circumstances
WebXRWalkingLocomotion can serve as an alternative to controller-based
continuous traversal. Early tests indicate that walking locomotion can
feel noticeably more comfortable than controller-based continuous
traversal, perhaps because the familiar "walking" motion reduces the
dissonance between the visual and vestibular stimuli presented to the
user.
It is also notable that WebXRWalkingLocomotion, because it assesses only
head motion, can be used entirely controller-free. This is particularly
powerful in combination with WebXRHandTracking because it allows for a
fully traversal-enabled VR experience where users can use their natural
hands without any controllers at all. This is not possible using other
traversal technologies without customizing the virtual space to support
point-to-point navigation and/or advanced hand gestures.