World Streaming
@esengine/world-streaming provides chunk-based world streaming and management for open world games. It handles dynamic loading/unloading of world chunks based on player position.
Installation
Section titled “Installation”npminstall@esengine/world-streamingQuick Start
Section titled “Quick Start”Basic Setup
Section titled “Basic Setup”import {ChunkManager,ChunkStreamingSystem,StreamingAnchorComponent,ChunkLoaderComponent} from'@esengine/world-streaming';// Create chunk manager (512 unit chunks)const chunkManager = newChunkManager(512);chunkManager.setScene(scene);// Add streaming systemconst streamingSystem = newChunkStreamingSystem();streamingSystem.setChunkManager(chunkManager);scene.addSystem(streamingSystem);// Create loader entity with configconst loaderEntity = scene.createEntity('ChunkLoader');const loader = loaderEntity.addComponent(newChunkLoaderComponent());loader.chunkSize=512;loader.loadRadius=2;loader.unloadRadius=4;// Create player as streaming anchorconst playerEntity = scene.createEntity('Player');const anchor = playerEntity.addComponent(newStreamingAnchorComponent());// Update anchor position each framefunctionupdate() {anchor.x= player.position.x;anchor.y= player.position.y;}Procedural Generation
Section titled “Procedural Generation”importtype { IChunkDataProvider, IChunkCoord, IChunkData } from'@esengine/world-streaming';classProceduralChunkProviderimplementsIChunkDataProvider {private seed:number;constructor(seed:number) {this.seed= seed;}asyncloadChunkData(coord:IChunkCoord):Promise<IChunkData|null> {// Use deterministic random based on seed + coordconstchunkSeed = this.hashCoord(coord);constrng = this.createRNG(chunkSeed);// Generate chunk contentconstentities = this.generateEntities(coord, rng);return {coord,entities,version: 1};}asyncsaveChunkData(data:IChunkData):Promise<void> {// Optional: persist modified chunks}privatehashCoord(coord:IChunkCoord):number {returnthis.seed^ (coord.x*73856093) ^ (coord.y*19349663);}privatecreateRNG(seed:number) {// Simple seeded randomreturn()=> {seed = (seed *1103515245+12345) &0x7fffffff;return seed /0x7fffffff;};}privategenerateEntities(coord:IChunkCoord, rng:()=>number) {// Generate resources, trees, etc.return [];}}// Use providerchunkManager.setDataProvider(newProceduralChunkProvider(12345));Core Concepts
Section titled “Core Concepts”Chunk Lifecycle
Section titled “Chunk Lifecycle”Unloaded → Loading → Loaded → Unloading → Unloaded↓ ↓Failed (on error)Streaming Anchor
Section titled “Streaming Anchor”StreamingAnchorComponent marks entities as chunk loading anchors. The system loads chunks around all anchors and unloads chunks outside the combined range.
// StreamingAnchorComponent implements IPositionableinterface IPositionable {readonly position: { x:number; y:number };}Configuration
Section titled “Configuration”| Property | Default | Description |
|---|---|---|
chunkSize | 512 | Chunk size in world units |
loadRadius | 2 | Chunks to load around anchor |
unloadRadius | 4 | Chunks to unload beyond this |
maxLoadsPerFrame | 2 | Max async loads per frame |
unloadDelay | 3000 | MS before unloading |
bEnablePrefetch | true | Prefetch in movement direction |
Module Setup (Optional)
Section titled “Module Setup (Optional)”For quick setup, use the module helper:
import { worldStreamingModule } from'@esengine/world-streaming';const chunkManager = worldStreamingModule.setup(scene,services,componentRegistry,{ chunkSize: 256, bEnableCulling: true });Documentation
Section titled “Documentation”- Chunk Manager API - Loading queue, chunk lifecycle
- Streaming System - Anchor-based loading
- Serialization - Custom chunk serialization
- Examples - Procedural worlds, MMO chunks