Needle Engine Documentation
Getting Started
Tutorials
How-To Guides
Explanation
Reference
Help
Getting Started
Tutorials
How-To Guides
Explanation
Reference
Help

XR Event Methods

Build immersive AR/VR experiences with WebXR event methods.


Component XR Events

MethodParametersWhen Called
supportsXRmode: XRSessionModeOptional: Filter which XR modes to support (immersive-vr, immersive-ar)
onBeforeXRmode: XRSessionMode
init: XRSessionInit
Before XR session starts (modify init options)
onEnterXRargs: NeedleXREventArgsComponent enters XR session
onUpdateXRargs: NeedleXREventArgsEvery frame during XR session
onLeaveXRargs: NeedleXREventArgsComponent exits XR session
onControllerAddedargs: NeedleXRControllerEventArgsVR controller connected or component joins session with controllers
onControllerRemovedargs: NeedleXRControllerEventArgsVR controller disconnected or component becomes inactive

XR Session Modes

type XRSessionMode =
    | "immersive-vr"  // VR headset
    | "immersive-ar"  // AR device
    | "inline";       // Non-immersive (not commonly used)

Example: Filter XR Support

Only enable component for VR (not AR):

import { Behaviour, XRSessionMode } from "@needle-tools/engine";

export class VROnlyComponent extends Behaviour {
    supportsXR(mode: XRSessionMode): boolean {
        // Only activate in VR sessions
        return mode === "immersive-vr";
    }

    onEnterXR(args: NeedleXREventArgs) {
        console.log("Entered VR mode");
    }
}

Example: XR Session Lifecycle

import { Behaviour, NeedleXREventArgs } from "@needle-tools/engine";

export class XRLifecycle extends Behaviour {
    onEnterXR(args: NeedleXREventArgs) {
        console.log("Entered XR session", args.xr.session);
        this.enableVRUI();
    }

    onUpdateXR(args: NeedleXREventArgs) {
        // Called every frame in XR
        this.updateVRControls();
    }

    onLeaveXR(args: NeedleXREventArgs) {
        console.log("Exited XR session");
        this.disableVRUI();
    }

    private enableVRUI() {
        // Show VR-specific UI
    }

    private updateVRControls() {
        // Update VR interaction every frame
    }

    private disableVRUI() {
        // Hide VR UI
    }
}

Example: VR Controller Events

import { Behaviour, NeedleXRControllerEventArgs } from "@needle-tools/engine";

export class VRControllerHandler extends Behaviour {
    onControllerAdded(args: NeedleXRControllerEventArgs) {
        console.log("Controller connected:", args.controller);

        // Access controller model
        const model = args.controller.controllerModel;

        // Check handedness
        if (args.controller.handedness === "left") {
            this.setupLeftController(args.controller);
        } else {
            this.setupRightController(args.controller);
        }
    }

    onControllerRemoved(args: NeedleXRControllerEventArgs) {
        console.log("Controller disconnected:", args.controller);
    }

    private setupLeftController(controller) {
        // Configure left controller
    }

    private setupRightController(controller) {
        // Configure right controller
    }
}

Global XR Events

For global XR session events (outside components):

EventTypeDescription
"needle-xrsession-start"CustomEventXR session starts (details.session = NeedleXRSession)
"needle-xrsession-end"CustomEventXR session ends (details.session = NeedleXRSession)
onXRSessionStartHookGlobal hook for session start (unsubscribe with offXRSessionStart)

Example: Global XR Events

// Using CustomEvent
window.addEventListener("needle-xrsession-start", (evt) => {
    console.log("XR Session started:", evt.detail.session);
});

// Using global hook
import { onXRSessionStart } from "@needle-tools/engine";

onXRSessionStart((args) => {
    console.log("XR Session started:", args.session);
});

Modify XR Session Init Options

import { Behaviour, XRSessionMode } from "@needle-tools/engine";

export class XRSessionConfig extends Behaviour {
    onBeforeXR(mode: XRSessionMode, init: XRSessionInit) {
        // Request specific features
        if (mode === "immersive-ar") {
            init.requiredFeatures = ["hit-test", "anchors"];
            init.optionalFeatures = ["hand-tracking"];
        }
    }
}

Related

  • XR Guide - Set up WebXR
  • Image Tracking - AR image tracking
  • Lifecycle Methods - Component lifecycle
Suggest changes
Last Updated: 1/27/26, 10:48 PM

On this page

Extras

Copy for AI (LLMs)