Skip to content

Network Sync Demo

This is an interactive demo showcasing @esengine/network network synchronization tools.

Left side is the client view (the player you control), right side is the server authoritative state. Switch between different modes to observe the effects of various synchronization strategies.

Controls:

  • Keyboard: WASD or arrow keys to move
  • Touch/Mouse: Virtual joystick in the bottom-left corner
Network Sync - State Synchronization & Client PredictionTS

Client directly responds to input without considering server state.

Problem: Client and server states gradually diverge, red warning ring shows divergence distance.

Client waits for server state, uses SnapshotBuffer for interpolation display.

Problem: Noticeable input delay (feels “sluggish”) because it waits for server confirmation.

Uses framework ClientPrediction API for immediate response, corrects when receiving server state.

Feature: Green dashed circle shows server’s actual position, may have slight position snapping.

Combines prediction + HermiteTransformInterpolator + smoothDamp smooth correction.

Features:

  • Green dashed line: Server’s actual position
  • Red arrow: Correction vector (from predicted to server position)
  • Remote players use Hermite curve interpolation for smoother movement
  • AI player follows a fixed figure-8 path for easier observation of sync effects

import { createSnapshotBuffer } from '@esengine/network';
// Create snapshot buffer
const buffer = createSnapshotBuffer<PlayerState>(
30, // maxSize: Maximum snapshot count
100 // interpolationDelay: Interpolation delay (ms)
);
// Store server state when received
buffer.push({
timestamp: serverTimestamp,
state: playerState
});
// Get snapshots for interpolation
const renderTime = Date.now() - 100;
const result = buffer.getInterpolationSnapshots(renderTime);
if (result) {
const [prevSnapshot, nextSnapshot, t] = result;
// t is the interpolation factor between 0~1
}
import { createClientPrediction } from '@esengine/network';
// Define predictor
const predictor = {
predict(state, input, deltaTime) {
return {
x: state.x + input.dx * SPEED * deltaTime,
y: state.y + input.dy * SPEED * deltaTime,
vx: input.dx * SPEED,
vy: input.dy * SPEED
};
}
};
// Create prediction manager
const prediction = createClientPrediction(predictor, {
maxUnacknowledgedInputs: 60,
reconciliationThreshold: 0.5,
reconciliationSpeed: 10
});
// Each frame: record input and predict
const predictedState = prediction.recordInput(input, currentState, deltaTime);
// When receiving server state: reconcile
const reconciledState = prediction.reconcile(
serverState,
acknowledgedSequence,
state => ({ x: state.x, y: state.y }),
deltaTime
);

3. HermiteTransformInterpolator - Hermite Curve Interpolation

Section titled “3. HermiteTransformInterpolator - Hermite Curve Interpolation”
import { createHermiteTransformInterpolator } from '@esengine/network';
// Create Hermite interpolator (smoother than linear interpolation)
const hermiteInterpolator = createHermiteTransformInterpolator();
// Use velocity information for smooth interpolation
const result = hermiteInterpolator.interpolate(
{ x: 0, y: 0, rotation: 0, velocityX: 10, velocityY: 0, angularVelocity: 0 },
{ x: 100, y: 50, rotation: 0, velocityX: 5, velocityY: 5, angularVelocity: 0 },
0.5 // t = 0.5
);
import { smoothDamp } from '@esengine/network';
// Smoothly transition to target value (used for correction offset)
const [newValue, newVelocity] = smoothDamp(
currentValue, // Current value
targetValue, // Target value
velocity, // Current velocity (will be updated)
smoothTime, // Smooth time
deltaTime, // Frame time
maxSpeed // Maximum speed (optional)
);

Server is the single "source of truth"
Client only "predicts" and "displays"
Server can detect any cheating attempts
renderTime = currentTime - interpolationDelay
Higher delay → Smoother, but more latency
Lower delay → More responsive, but may stutter
Recommended: 100-150ms (adjustable via parameter panel)
Prediction: Respond immediately, better feel
Correction: Smooth fix when receiving server state
Key: Use smoothDamp to avoid "jumping"
Linear: Simple, but not smooth when turning
Hermite: Uses velocity info, more natural curves
Recommended: Use Hermite for remote players