Skip to content

Unreal

The Unreal Engine (web export) connector. Unreal renders into a <canvas> via WebAssembly, so it is built on the web-export foundation and works in two tiers: a JS-only tier (no engine code — pointer heatmaps, FPS, JS errors) and a bridged tier (a thin copy-in shim adds camera pose, world-space picks, and replay).

Terminal window
npm install @uptimizr/unreal
import { trackUnreal } from "@uptimizr/unreal";
const { client, bridge } = trackUnreal({
projectId: "your-project",
endpoint: "https://collect.example.com",
canvas: () => document.querySelector("#unreal-canvas"),
});
// later, on teardown
await client.stop("manual");

trackUnreal creates the client, registers the JS-only tier collector, exposes the engine bridge (default window.__uptimizr_unreal__), and starts the session with Unreal’s connector provenance. The JS-only tier captures immediately; wire the engine-side shim to bridge to add camera pose, picks, and replay.

The bridged tier uses a thin copy-in shim — Emscripten EM_JS / cwrap glue that samples the active APlayerCameraManager pose, raycast picks, and FPS each frame and calls the bridge. It’s a copy-in asset, not an npm dependency. The shim ships in the package under bridge/Uptimizr.h

  • Uptimizr.cpp — alongside a README covering the supported web targets and wiring. Copy both files into your project’s web target, call UptimizrTelemetry().Initialize() (which asserts the bridge protocol version matches), then UptimizrTelemetry().Tick(GetWorld(), DeltaSeconds) each frame.

Unreal’s native world frame is left-handed, z-up, centimeters, so the connector rebases z-up → y-up, converts cm → m, and reaches the canonical wire frame (left-handed, y-up, unit scale 1). The engine-side shim pushes raw Unreal values — the connector owns the single normalization path. The session records Unreal’s native frame in connector.coordinateSystem.

JS-only tier: pointer move/click → screen heatmaps, FPS / long frames → performance, JS errors. Bridged tier: camera pose → view-direction heatmap, world-space picks → object engagement, scene proxy, and replay.

No client-side persistent IDs and no PII by default (ADR 0003). client.stop() tears down every listener, timer, and animation-frame callback.