Input and movement

Controllers, hands, and the uncomfortable problem of moving someone through a space they are standing still in.

Input in XR is not events. There is no click, no keydown, no element under the pointer. On every frame you are handed a set of input sources, each with a pose, a gamepad-like button state, and possibly a 25-joint hand skeleton — and it is your job to decide what any of that means. A pinch, a grab, a pointer ray, a teleport arc: none of them exist in the API. You build them from poses.

The three pages here go from the concrete to the contested. Controllers is the most mechanical: input sources, the targetRay versus grip distinction that trips up almost everyone once, button and axis state, and haptics. Hand tracking replaces the buttons with geometry — the same input model, but now a gesture is a distance between two joints and a threshold you picked. Locomotion is the one with no correct answer, because the constraint is not technical.

That last page is the reason this section exists as a group rather than three unrelated topics. Every input decision in XR eventually runs into the body: a ray is easier to aim than a hand but less direct, a pinch threshold that feels crisp to you registers as a missed grab for someone else, and smooth locomotion that looks best in a video is the one that sends a portion of your users to sit down. The API gives you poses. Comfort is a design problem you cannot read off the spec.

In this section

  1. VR controllersA controller reaches your code as an XRInputSource: two separate spaces, an optional gamepad, and a select event that works the same on every device — including the ones with no controller at all.
  2. Hand trackingA tracked hand arrives as an XRHand: a map of 25 named joints, each with its own pose, orientation and radius — and each one allowed to be missing on any given frame.
  3. Locomotion and comfortYou never move the camera in WebXR. You replace the reference space with an offset copy of itself — and the difference between doing that instantly and doing it gradually is the difference between a comfortable app and a nauseating one.

Read these in order

Controllers establishes the input-source model — how a frame hands you devices, poses and button state. Hand tracking assumes you already have that model and swaps in a skeleton.

Locomotion comes last on purpose. It is the page that depends on both of the others and on a judgement call neither of them requires: how much movement you are willing to impose on someone who is not actually moving.