@3dsource/angular-unreal-module
v0.0.168
Published
Angular integration for Unreal Engine Pixel Streaming
Readme
@3dsource/angular-unreal-module
Standalone Angular integration for Unreal Engine Pixel Streaming. The package provides the scene component, WebRTC and signalling lifecycle, NgRx state, command/callback APIs, reconnection, file transfer and telemetry.
Requirements
- Angular, Angular CDK and Angular Forms
>=19.0.0 <23.0.0 - NgRx Store and Effects
>=19.0.0 <23.0.0 - RxJS
>=7.8.0 <8.0.0 @3dsource/types-unreal >=0.0.7@3dsource/utils >=1.0.21provideHttpClient()in the host application
Installation
pnpm add @3dsource/angular-unreal-module @3dsource/types-unreal @3dsource/utilsThe package is standalone and does not expose an NgModule.
Styling
The package ships its own styles and does not require any UI library. Its
components read --src-* design tokens where available, but every token has a
built-in fallback, so @3dsource/source-ui-native is entirely optional: install
it in the host application only if you want the components to follow that theme.
Setup
1. Register state and configuration once
Add the Unreal feature state, HTTP client and configuration at the application
root. UNREAL_CONFIG is required, although all its fields are optional.
import { provideHttpClient } from '@angular/common/http';
import type { ApplicationConfig } from '@angular/core';
import { provideStore } from '@ngrx/store';
import {
provideUnrealState,
UNREAL_CONFIG,
type UnrealInitialConfig,
} from '@3dsource/angular-unreal-module';
const unrealConfig = {
regionsPingUrl: 'https://datacenter.3dsource.com/regions/',
dataChannelConnectionTimeout: 8000,
fpsMonitor: false,
autoHighResolution: false,
} satisfies UnrealInitialConfig;
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(),
provideStore(),
provideUnrealState(),
{ provide: UNREAL_CONFIG, useValue: unrealConfig },
],
};Omit provideStore() when the root NgRx store is already configured.
Available configuration fields:
| Field | Purpose |
| ------------------------------ | ---------------------------------------------- |
| regionsPingUrl | Region latency endpoint |
| dataChannelConnectionTimeout | DataChannel connection timeout in ms |
| customErrorsEndpoint | Custom error reporting endpoint |
| commandTelemetryReceiver | Command telemetry endpoint |
| streamTelemetryV2Url | Stream lifecycle telemetry endpoint |
| screenLockerContainerId | Container used by the screen-locker overlay |
| fpsMonitor | Enables FPS monitoring |
| autoHighResolution | Raises resolution after the scene becomes idle |
| playwright | Enables the test-specific service behaviour |
Use { provide: UNREAL_CONFIG, useValue: {} } for the minimal configuration.
2. Boot the engine on a lazy route
Lazy-load the route file from the application router:
import type { Routes } from '@angular/router';
export const APP_ROUTES: Routes = [
{
path: 'stream',
loadChildren: () =>
import('./stream/stream.routes').then((module) => module.STREAM_ROUTES),
},
];Register provideUnrealModule() inside that lazy route file:
import type { Routes } from '@angular/router';
import { provideUnrealModule } from '@3dsource/angular-unreal-module';
import { StreamComponent } from './stream.component';
export const STREAM_ROUTES: Routes = [
{
path: '',
component: StreamComponent,
providers: [provideUnrealModule()],
},
];Keep provideUnrealState() and UNREAL_CONFIG at the application root.
The loadChildren() boundary keeps the streaming engine out of the initial
bundle. Route-scoping provideUnrealModule() tears down its effects when the
route is left.
UNREAL_CONFIGon a route'sprovidersdoes not work: the engine services areprovidedIn: 'root', so they are created by the root injector and read the token from there. A route-level value is invisible to them andinject(UNREAL_CONFIG, { optional: true })resolves tonull— e.g. region pinging is skipped entirely (emptyregionsPingUrl), the orchestrationrequestStreamgoes out without a region and the post-connection re-ping never runs. Importing only the token at the root does not pull the module into the initial bundle (the package issideEffects: false).
3. Render the scene
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { UnrealSceneComponent } from '@3dsource/angular-unreal-module';
@Component({
selector: 'app-stream',
imports: [UnrealSceneComponent],
template: `<app-unreal-scene />`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class StreamComponent {}UnrealSceneComponent also accepts isStudio,
useContainerAsSizeProvider and resolutionSize inputs, and emits
changeMouseOverScene.
Main API
provideUnrealState()— registers theunrealFeatureNgRx state.provideUnrealModule()— registers effects and boots streaming services.UnrealSceneComponent— renders and manages the Pixel Streaming scene.UnrealCommunicatorService— sends commands and UI interactions.UnrealCallbackService— observes Unreal callbacks and command responses.unrealFeature, exported selectors and actions — expose connection and scene lifecycle state.
Command packet types are provided by @3dsource/types-unreal.
Run pnpm demo:start from the repository root to see the scene component in
the demo application.
Optional prefetch scripts
The package publishes two dependency-free scripts for use in the document
<head> before Angular starts:
region-ping-prefetch.jsmeasures regions early and caches the closest one.stream-prefetch.jsopens and parks an eligible WebRTC connection so Angular can adopt it after bootstrap.
<script
src="https://cdn.jsdelivr.net/npm/@3dsource/angular-unreal-module/js/region-ping-prefetch.js"
async
></script>
<script
src="https://cdn.jsdelivr.net/npm/@3dsource/angular-unreal-module/js/stream-prefetch.js"
async
></script>stream-prefetch.js runs by default only on
metabox-configurator/{modular|basic}/... routes. It reads the same-origin
assets/config.json; override that path with data-config-url when needed.
It also forwards the orchestration-issued streamRequestId from the polling
response to Cirrus on the WebSocket URL (the session connectionId) and parks it
for the Angular side to adopt.
Pin an exact package version in production when deterministic CDN assets are
required.
Repository development
Run commands from the repository root:
pnpm unreal:build
pnpm unreal:build:watch
pnpm unreal:lint
pnpm unreal:test
pnpm unreal:test:watch
pnpm unreal:test:signalling
pnpm unreal:test:signalling:leaksunreal:build builds the local types-unreal and utils dependencies before
this package.
Release commands publish only this package:
pnpm unreal:release:patch
pnpm unreal:release:devAfter a successful publish, the release automatically purges the matching jsDelivr tag. Retry a failed purge without rerunning the release:
pnpm unreal:purge-cdn -- latest
pnpm unreal:purge-cdn -- devRepository tooling requires Node.js 24.16.0 or newer and pnpm 11.18.0.
