| name | xb-core |
| description | Bootstrap and structure an XR Blocks app: the `xb.Script` lifecycle, `xb.Options` configuration with chainable `enable*()` methods, the global aliases (`xb.core`, `xb.user`, `xb.scene`, `xb.world`, `xb.ai`…), and how to add objects and run the app in the desktop simulator or on an XR device. Use this first whenever creating a new XR Blocks experience or wiring up the main entry point, the frame loop (`update`), or select/pinch/click and key input. Other skills (xb-ui, xb-hands, xb-depth, xb-ai, …) build on this foundation. |
xb-core: bootstrap an XR Blocks app
Every app is one or more xb.Script subclasses registered with xb.add() before
xb.init(options). Core owns the renderer, camera, WebXR session, and frame loop — never
roll your own. Full overview: ../../src/SKILL.md.
Canonical app
import * as THREE from 'three';
import * as xb from 'xrblocks';
class MainScript extends xb.Script {
init() {
this.add(new THREE.HemisphereLight(0xffffff, 0x666666, 3));
this.cube = new THREE.Mesh(
new THREE.BoxGeometry(0.3, 0.3, 0.3),
new THREE.MeshStandardMaterial({color: 0x4285f4})
);
this.cube.position.set(0, xb.user.height - 0.3, -xb.user.objectDistance);
this.add(this.cube);
}
update(time, frame) {
this.cube.rotation.y += xb.getDeltaTime();
}
onSelectEnd() {
this.cube.material.color.set(Math.random() * 0xffffff);
}
}
document.addEventListener('DOMContentLoaded', () => {
xb.add(new MainScript());
xb.init(new xb.Options());
});
Configure with Options
const options = new xb.Options();
options.enableUI();
options.enableHands();
options.enableAI();
options.setAppTitle?.('My App');
xb.init(options);
Chainable feature toggles: enableUI, enableReticles, enableControllers, enableHands,
enableHandRays, enableGestures, enableStrokes, enableDepth, enablePlaneDetection,
enableObjectDetection, enableCamera, enableAI, enableXRTransitions, enableVR.
Physics and lighting are configured directly (see xb-physics; options.lighting).
Lifecycle hooks
init(deps?), update(time?, frame?), initPhysics(physics)/physicsStep(),
onSelectStart/End, onSqueezeStart/End, onKeyDown/Up (e.code),
onXRSessionStarted(session?)/onXRSessionEnded(), onSimulatorStarted().
Object-targeted hooks fire on the Script whose subtree was hit; return true to stop
propagation: onObjectSelectStart/End, onObjectTouchStart/Touching/End,
onObjectGrabStart/Grabbing/End, onHoverEnter/Hovering/Exit.
Globals
xb.core (engine), xb.scene, xb.user, xb.world, xb.ai, xb.depth, xb.sound,
xb.input, xb.camera; helpers xb.add(), xb.init(), xb.getDeltaTime(),
xb.getElapsedTime(). Useful xb.user members: height, objectDistance, panelDistance,
isSelecting(), isSelectingAt(obj), isPointingAt(obj), getReticleTarget(id).
Run it
npm ci && npm run dev
Open your sample/template under that URL. The desktop simulator lets you develop without a
headset; ?formFactor=desktop autostarts it (see xb-simulator).
Pitfall: subsystems created during xb.init() (e.g. xb.core.renderer) are undefined
in a constructor — use them in/after init().