Serialization System
The serialization system provides a complete solution for persisting scene, entity, and component data. It supports both full serialization and incremental serialization modes, suitable for game saves, network synchronization, scene editors, time rewinding, and more.
Basic Concepts
Section titled “Basic Concepts”The serialization system has two layers:
- Full Serialization: Serializes the complete scene state, including all entities, components, and scene data
- Incremental Serialization: Only serializes changes relative to a base snapshot, greatly reducing data size
Supported Data Formats
Section titled “Supported Data Formats”- JSON Format: Human-readable, convenient for debugging and editing
- Binary Format: Uses MessagePack, smaller size and better performance
v2.2.2 Important Change
Starting from v2.2.2, binary serialization returns
Uint8Arrayinstead of Node.jsBufferto ensure browser compatibility:
serialize({ format: 'binary' })returnsstring | Uint8Array(wasstring | Buffer)deserialize(data)acceptsstring | Uint8Array(wasstring | Buffer)applyIncremental(data)acceptsIncrementalSnapshot | string | Uint8Array(was includingBuffer)Migration Impact:
- Runtime Compatible: Node.js
Bufferinherits fromUint8Array, existing code works directly- Type Checking: If your TypeScript code explicitly uses
Buffertype, change toUint8Array- Browser Support:
Uint8Arrayis a standard JavaScript type supported by all modern browsers
Full Serialization
Section titled “Full Serialization”Basic Usage
Section titled “Basic Usage”1. Mark Serializable Components
Section titled “1. Mark Serializable Components”Use @Serializable and @Serialize decorators to mark components and fields for serialization:
import { Component, ECSComponent, Serializable, Serialize } from '@esengine/ecs-framework';
@ECSComponent('Player')@Serializable({ version: 1 })class PlayerComponent extends Component { @Serialize() public name: string = '';
@Serialize() public level: number = 1;
@Serialize() public experience: number = 0;
@Serialize() public position: { x: number; y: number } = { x: 0, y: 0 };
// Fields without @Serialize() won't be serialized private tempData: any = null;}2. Serialize Scene
Section titled “2. Serialize Scene”// JSON format serializationconst jsonData = scene.serialize({ format: 'json', pretty: true // Pretty print output});
// Save to local storagelocalStorage.setItem('gameSave', jsonData);
// Binary format serialization (smaller size)const binaryData = scene.serialize({ format: 'binary'});
// Save to file (Node.js environment)// Note: binaryData is Uint8Array type, Node.js fs can write it directlyfs.writeFileSync('save.bin', binaryData);3. Deserialize Scene
Section titled “3. Deserialize Scene”// Restore from JSONconst saveData = localStorage.getItem('gameSave');if (saveData) { scene.deserialize(saveData, { strategy: 'replace' // Replace current scene content });}
// Restore from Binaryconst binaryData = fs.readFileSync('save.bin');scene.deserialize(binaryData, { strategy: 'merge' // Merge into existing scene});Serialization Options
Section titled “Serialization Options”SerializationOptions
Section titled “SerializationOptions”interface SceneSerializationOptions { // Component types to serialize (optional) components?: ComponentType[];
// Serialization format: 'json' or 'binary' format?: 'json' | 'binary';
// Pretty print JSON output pretty?: boolean;
// Include metadata includeMetadata?: boolean;}Example:
// Only serialize specific component typesconst saveData = scene.serialize({ format: 'json', components: [PlayerComponent, InventoryComponent], pretty: true, includeMetadata: true});DeserializationOptions
Section titled “DeserializationOptions”interface SceneDeserializationOptions { // Deserialization strategy strategy?: 'merge' | 'replace';
// Component type registry (optional, uses global registry by default) componentRegistry?: Map<string, ComponentType>;}Scene Custom Data
Section titled “Scene Custom Data”Besides entities and components, you can also serialize scene-level configuration data:
// Set scene datascene.sceneData.set('weather', 'rainy');scene.sceneData.set('difficulty', 'hard');scene.sceneData.set('checkpoint', { x: 100, y: 200 });
// Scene data is automatically included when serializingconst saveData = scene.serialize({ format: 'json' });
// Scene data is restored after deserializationscene.deserialize(saveData);console.log(scene.sceneData.get('weather')); // 'rainy'More Topics
Section titled “More Topics”- Decorators & Inheritance - Advanced decorator usage and component inheritance
- Incremental Serialization - Only serialize changes
- Version Migration - Handle data structure changes
- Use Cases - Save system, network sync, undo/redo examples