@uptimizr/unreal 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +137 -0
- package/README.md +8 -3
- package/dist/uptimizr-unreal.global.js +22 -17
- package/dist/uptimizr-unreal.js +22 -17
- package/llms.txt +31 -0
- package/package.json +8 -6
package/AGENTS.md
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# AGENTS.md — @uptimizr/unreal
|
|
2
|
+
|
|
3
|
+
> Packaged agent guide. For the human reference see [README.md](./README.md); for design
|
|
4
|
+
> rationale see the project ADRs at https://github.com/RaananW/Uptimizr/tree/main/docs/adr.
|
|
5
|
+
|
|
6
|
+
## What this package is
|
|
7
|
+
|
|
8
|
+
The **Unreal Engine (web export)** connector for Uptimizr (ADR 0045). Unreal renders into a
|
|
9
|
+
`<canvas>` via WebAssembly, so there is no live JS scene to duck-type. This package is a thin
|
|
10
|
+
engine-flavoured wrapper over [`@uptimizr/web-export`](../web-export) and works in **two tiers**:
|
|
11
|
+
|
|
12
|
+
| Tier | Engine code? | Captures |
|
|
13
|
+
| ----------- | ----------------------------------------------- | --------------------------------------------------------------- |
|
|
14
|
+
| **JS-only** | none | pointer move/click heatmaps, FPS / long frames, JS errors |
|
|
15
|
+
| **Bridged** | a thin copy-in shim (see [`bridge/`](./bridge)) | camera pose → view-direction heatmap, world-space picks, replay |
|
|
16
|
+
|
|
17
|
+
Unreal's native world frame is **left-handed, z-up, centimeters** (`UNREAL_FRAME`,
|
|
18
|
+
`unitScale: 100`). It is the only engine that exercises the non-`y` up-axis and non-1 unit-scale
|
|
19
|
+
paths: the connector rebases **z-up → y-up** and converts **cm → m** before reaching the canonical
|
|
20
|
+
wire frame (ADR 0018 / ADR 0045 §5). The engine-side shim does **no** coordinate math.
|
|
21
|
+
|
|
22
|
+
**Status — best-effort by design.** Epic deprecated the official HTML5/Emscripten target after
|
|
23
|
+
UE 4.24, and Pixel Streaming renders server-side (no client WASM scene to read), so neither fits
|
|
24
|
+
this model. The shim targets the real Emscripten-based, client-side web exports — community HTML5
|
|
25
|
+
forks (UE 4.24–4.27, WebGL2) and Wonder Interactive / SimplyStream (UE 5.1–5.4, WASM + WebGPU).
|
|
26
|
+
Every viable target is experimental or community-maintained, so the **bridged tier is best-effort**;
|
|
27
|
+
the JS-only tier always works on any web export that renders into a `<canvas>`.
|
|
28
|
+
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pnpm add @uptimizr/unreal
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The engine-side bridge is a **copy-in asset**, not an npm dependency — see [`bridge/`](./bridge).
|
|
36
|
+
|
|
37
|
+
## Canonical usage — the web side
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import { trackUnreal } from "@uptimizr/unreal";
|
|
41
|
+
|
|
42
|
+
const { client, bridge } = trackUnreal({
|
|
43
|
+
projectId: "your-project",
|
|
44
|
+
endpoint: "https://collect.example.com",
|
|
45
|
+
canvas: () => document.querySelector("#unreal-canvas"),
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// ... later, on teardown
|
|
49
|
+
await client.stop("manual");
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`trackUnreal` creates the client, registers the JS-only tier collector, publishes the engine
|
|
53
|
+
`bridge` (default `window.__uptimizr_unreal__`), and starts the session with Unreal's connector
|
|
54
|
+
provenance. Run it **before** the export boots so the bridge global exists when the shim
|
|
55
|
+
initializes. `client` is the `@uptimizr/sdk-core` `UptimizrClient` — read `client.sessionId`,
|
|
56
|
+
`client.track(name, props)`, `client.setScene(sceneId)`, `client.stop(reason)`.
|
|
57
|
+
|
|
58
|
+
### Advanced (compose it yourself)
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { UptimizrClient } from "@uptimizr/sdk-core";
|
|
62
|
+
import { unrealCollector, UNREAL_FRAME } from "@uptimizr/unreal";
|
|
63
|
+
|
|
64
|
+
const client = new UptimizrClient({ projectId: "your-project", endpoint: "..." });
|
|
65
|
+
client.use(unrealCollector({ canvas: () => document.querySelector("#unreal-canvas") }));
|
|
66
|
+
client.start();
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Options are `@uptimizr/web-export`'s `TrackWebExportOptions` with `name` and `frame` omitted
|
|
70
|
+
(they are fixed to `"unreal"` / `UNREAL_FRAME`): `canvas`, `capture`, `pointerMoveThrottleMs`,
|
|
71
|
+
`perfWindowMs`, `jankFrameMs`, `sceneId`, `bridgeGlobal`, `onSceneProxy`, `version`,
|
|
72
|
+
`flushIntervalMs`, `transport`, `disabled`, `debug`, `user`, `meta`.
|
|
73
|
+
|
|
74
|
+
## Canonical usage — the engine side
|
|
75
|
+
|
|
76
|
+
The bridged tier needs a thin copy-in Emscripten shim: [`bridge/Uptimizr.h`](./bridge/Uptimizr.h)
|
|
77
|
+
and [`bridge/Uptimizr.cpp`](./bridge/Uptimizr.cpp).
|
|
78
|
+
|
|
79
|
+
1. Copy both into your project's `Source/<Module>/` (or a plugin) so they build with your **web**
|
|
80
|
+
target.
|
|
81
|
+
2. Load `@uptimizr/unreal` in the export's host page and call `trackUnreal({...})`.
|
|
82
|
+
3. Drive the sampler from C++:
|
|
83
|
+
|
|
84
|
+
```cpp
|
|
85
|
+
#include "Uptimizr.h"
|
|
86
|
+
|
|
87
|
+
UptimizrTelemetry().Initialize(); // once, after the page connector is up
|
|
88
|
+
UptimizrTelemetry().Tick(GetWorld(), DeltaSeconds); // every frame
|
|
89
|
+
UptimizrTelemetry().TraceAndReportPick(GetWorld()); // from your click handler
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
…or drive `Init` / `Shutdown` from JS by symbol via `cwrap`
|
|
93
|
+
(`Module.cwrap('UptimizrBridge_Init', 'number', [])`).
|
|
94
|
+
|
|
95
|
+
`Initialize()` reads the live bridge's `protocolVersion` and asserts it equals
|
|
96
|
+
`UPTIMIZR_BRIDGE_PROTOCOL_VERSION` (`1`), staying disabled on a mismatch. `Tick` reads the active
|
|
97
|
+
`APlayerCameraManager` pose and accumulates FPS, pushing a pose every frame and a perf sample about
|
|
98
|
+
once per second. Outside Emscripten (e.g. the desktop editor) every entry point compiles to a
|
|
99
|
+
**no-op**, so the shim is safe to leave wired into every build target.
|
|
100
|
+
|
|
101
|
+
## Rules for agents
|
|
102
|
+
|
|
103
|
+
- **Push raw Unreal values — centimeters, z-up, left-handed.** Do **not** pre-convert in the shim;
|
|
104
|
+
the TypeScript connector owns the single normalization path so every engine stays consistent
|
|
105
|
+
(ADR 0045 §4/§5).
|
|
106
|
+
- **The shim does no schema mapping.** Events live once in `@uptimizr/schema` and are emitted by
|
|
107
|
+
the connector.
|
|
108
|
+
- **Never invent identifiers engine-side** and never forward raw input text (ADR 0003/0045 §6).
|
|
109
|
+
Only poses, FPS and developer-assigned **named** objects cross the bridge (a pick sends the
|
|
110
|
+
actor's `GetName()` and the world hit point). No client-side persistent IDs; the server assigns
|
|
111
|
+
the cookieless visitor hash.
|
|
112
|
+
- `UNREAL_FRAME` is `{ handedness: "left", upAxis: "z", unitScale: 100 }` — it is the regression
|
|
113
|
+
canary for the non-y / non-1 normalization paths. Changing it silently corrupts every
|
|
114
|
+
world-space aggregate.
|
|
115
|
+
- Capture channels that need the engine (camera pose, world-space picks, scene proxy, replay) are
|
|
116
|
+
simply **absent** without the shim — do not fake them from the DOM.
|
|
117
|
+
- `registerRegions(sceneId, regions, { endpoint, apiKey })` (from `@uptimizr/sdk-core`) declares a
|
|
118
|
+
scene's named regions. It **replaces** the scene's set and needs an **`annotate`**-capable key —
|
|
119
|
+
never ship that key in a public bundle; call it from build/deploy/admin code.
|
|
120
|
+
- Native (non-web) Unreal builds and **Pixel Streaming** are out of scope (ADR 0045): server-side
|
|
121
|
+
rendering has no client WASM scene to read.
|
|
122
|
+
|
|
123
|
+
## Export / build caveats
|
|
124
|
+
|
|
125
|
+
- You need an **Emscripten-based, client-side** web target (a community HTML5 fork, or Wonder
|
|
126
|
+
Interactive / SimplyStream). There is no official Epic web target to build against.
|
|
127
|
+
- The shim compiles to no-ops off Emscripten, so it can stay in the module for every target.
|
|
128
|
+
- Point `canvas` at the export's real canvas element and start `trackUnreal` before the export
|
|
129
|
+
boots.
|
|
130
|
+
|
|
131
|
+
## More
|
|
132
|
+
|
|
133
|
+
- Package reference: [README.md](./README.md)
|
|
134
|
+
- Engine-side bridge: [`bridge/README.md`](./bridge/README.md)
|
|
135
|
+
- Unreal guide: https://uptimizr.com/docs/connectors/unreal/
|
|
136
|
+
- Shared foundation: [`@uptimizr/web-export`](../web-export/AGENTS.md)
|
|
137
|
+
- Integration guide: https://github.com/RaananW/Uptimizr/blob/main/docs/integration.md
|
package/README.md
CHANGED
|
@@ -61,9 +61,14 @@ client.start();
|
|
|
61
61
|
## Engine-side bridge
|
|
62
62
|
|
|
63
63
|
The bridged tier needs a thin copy-in shim that pushes world-space pose / picks / FPS
|
|
64
|
-
across Unreal's Emscripten glue.
|
|
65
|
-
[`bridge/
|
|
66
|
-
|
|
64
|
+
across Unreal's Emscripten glue. It ships in [`bridge/`](./bridge) as
|
|
65
|
+
[`Uptimizr.h`](./bridge/Uptimizr.h) + [`Uptimizr.cpp`](./bridge/Uptimizr.cpp): copy both
|
|
66
|
+
into your project's `Source/<Module>/` (or a plugin) so they build with your **web**
|
|
67
|
+
target, then drive `UptimizrTelemetry().Initialize()` / `.Tick(World, DeltaSeconds)` /
|
|
68
|
+
`.TraceAndReportPick(World)` from C++ (or `Init` / `Shutdown` from JS via `cwrap`). Off
|
|
69
|
+
Emscripten every entry point compiles to a no-op. `Initialize()` asserts the live bridge's
|
|
70
|
+
`protocolVersion` matches `UPTIMIZR_BRIDGE_PROTOCOL_VERSION` (1). The full contract, the
|
|
71
|
+
viable web targets, and an `EM_JS` sketch are in [`bridge/README.md`](./bridge/README.md).
|
|
67
72
|
|
|
68
73
|
## Privacy
|
|
69
74
|
|