Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commit9a85df95a3

README.md

xr_embodiment

The local player's body in a headset: which entity it is and why, the eyes seated in it, its head hidden from the eyes alone, its arms reaching for the hands, and the choice between that and the game's own camera. The public surface is xr.body, xr.perspective, xr.setPerspective and xr.perspectiveStatus; this module is what they call, and it runs the presentation while a session draws frames in play mode.

local Embodiment = require("@builtin::modules.api.engine.xr_embodiment")

local body = Embodiment.findBody()        -- { entity, reason } or nil
Embodiment.setPerspective("game")         -- the person's client setting `xr.perspective`
print(Embodiment.status().why)

What it does each frame

  1. Finds the body in order: the avatar bound to the local player, the entity the game's camera follows, the entity the local player's character controller moves. A candidate is the body only when the game uses it (usedByGame): the game's camera follows it or a character controller the local player drives moves it. The search repeats every BODY_RECHECK_SECONDS.
  2. States the eyes' point to the engine (__xr.setRigPosition): the body's root, the offset the eyes keep from it, and the body's eye height straight up.
  3. Draws the body's skinned meshes a second time for the eyes with the head bone collapsed (SkinnedModel.collapsedBones), on the layer xrEyes; the meshes themselves draw on xrSelf, which the eyes do not draw. Parts below the head bone (a hat, hair) and name labels draw on xrSelf alone.
  4. Adds an IKRig to the body with a hand target for each hand, and follows each hand (xr.hand) with the matching arm: the target stands at the wrist and turns to the palm, so the arm reaches the wrist and the hand bone takes the hand's orientation. A hand holding a controller turns with the controller's grip; a tracked bare hand turns with its palm.
  5. States the hand's finger directions (xr.hand(role).directions) to the rig, which points each finger bone of the avatar's hand along its direction. A hand holding a controller curls its fingers around the grip by the trigger and grip travel. The targets are synced entities and the rig's fields sync, so the players who see the body see the same hands; a still hand states nothing new.
  6. Follows the head with the body (xr_body): real steps carry it through the character controller, the torso turns toward the head's way, the spine bends and the hips move to the head, and the legs step so the feet stay planted. The eyes stay where the real head is.
  7. Reads a click of the right thumbstick as the switch between the two perspectives.

Testing without a headset

setInput(source) replaces the tracked devices with a table of drawing(), pose(role), controller(hand) and optionally hand(role) (the shape of xr.hand); tick(dt) runs one frame. setInput(nil) reads the session again.

What the person sees of their hands

tickHands(dt) runs in every mode while a session draws frames. It shows the hand and controller models (xr_models; a hand the body draws with its own arm has no model), draws the arc of a teleport (xr_gestures) and states the layers the eyes draw: xrSelf is never drawn by the eyes and xrEyes always is. bodyHands() says which hands the body draws.