网络同步演示
这是一个演示 @esengine/network 网络同步工具的交互式 demo。
左侧是客户端视角(你控制的玩家),右侧是服务器权威状态。通过切换不同模式,观察各种同步策略的效果。
操作说明:
- 键盘: WASD 或方向键移动
- 触摸/鼠标: 左下角虚拟摇杆
四种同步模式对比
Section titled “四种同步模式对比”1. 无同步
Section titled “1. 无同步”客户端直接响应输入,完全不考虑服务器状态。
问题:客户端和服务器状态会逐渐偏离,红色警告圈显示偏差距离。
2. 插值同步
Section titled “2. 插值同步”客户端等待服务器状态,使用 SnapshotBuffer 进行插值显示。
问题:输入延迟明显(感觉”黏糊糊”),因为需要等待服务器确认。
3. 客户端预测
Section titled “3. 客户端预测”使用框架 ClientPrediction API 立即响应输入,收到服务器状态后校正。
特点:绿色虚线圈显示服务器真实位置,可能出现轻微位置回跳。
4. 完整方案
Section titled “4. 完整方案”结合预测 + HermiteTransformInterpolator + smoothDamp 平滑校正。
特点:
- 绿色虚线:服务器真实位置
- 红色箭头:校正向量(从预测位置指向服务器位置)
- 远程玩家使用 Hermite 曲线插值,移动更平滑
- AI 玩家按固定 8 字形路径移动,便于观察同步效果
使用的框架 API
Section titled “使用的框架 API”1. SnapshotBuffer - 快照缓冲区
Section titled “1. SnapshotBuffer - 快照缓冲区”import { createSnapshotBuffer } from '@esengine/network';
// 创建快照缓冲区const buffer = createSnapshotBuffer<PlayerState>( 30, // maxSize: 最大快照数量 100 // interpolationDelay: 插值延迟(ms));
// 收到服务器状态时存入buffer.push({ timestamp: serverTimestamp, state: playerState});
// 获取插值用的快照const renderTime = Date.now() - 100;const result = buffer.getInterpolationSnapshots(renderTime);
if (result) { const [prevSnapshot, nextSnapshot, t] = result; // t 是 0~1 之间的插值因子}2. ClientPrediction - 客户端预测
Section titled “2. ClientPrediction - 客户端预测”import { createClientPrediction } from '@esengine/network';
// 定义预测器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 }; }};
// 创建预测管理器const prediction = createClientPrediction(predictor, { maxUnacknowledgedInputs: 60, reconciliationThreshold: 0.5, reconciliationSpeed: 10});
// 每帧:记录输入并预测const predictedState = prediction.recordInput(input, currentState, deltaTime);
// 收到服务器状态时:校正const reconciledState = prediction.reconcile( serverState, acknowledgedSequence, state => ({ x: state.x, y: state.y }), deltaTime);3. HermiteTransformInterpolator - Hermite 曲线插值
Section titled “3. HermiteTransformInterpolator - Hermite 曲线插值”import { createHermiteTransformInterpolator } from '@esengine/network';
// 创建 Hermite 插值器(比线性插值更平滑)const hermiteInterpolator = createHermiteTransformInterpolator();
// 使用速度信息进行平滑插值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);4. smoothDamp - 平滑阻尼
Section titled “4. smoothDamp - 平滑阻尼”import { smoothDamp } from '@esengine/network';
// 平滑过渡到目标值(用于校正偏移量)const [newValue, newVelocity] = smoothDamp( currentValue, // 当前值 targetValue, // 目标值 velocity, // 当前速度(会被更新) smoothTime, // 平滑时间 deltaTime, // 帧时间 maxSpeed // 最大速度(可选));网络同步最佳实践
Section titled “网络同步最佳实践”1. 服务器权威
Section titled “1. 服务器权威”服务器是唯一的"真相来源"客户端只是"预测"和"展示"任何作弊行为服务器都能检测2. 插值延迟
Section titled “2. 插值延迟”renderTime = currentTime - interpolationDelay
插值延迟越大 → 越平滑,但延迟越高插值延迟越小 → 越即时,但可能卡顿推荐值: 100-150ms(可通过参数面板调整)3. 预测与校正
Section titled “3. 预测与校正”预测: 立即响应输入,提升手感校正: 收到服务器状态后平滑修正关键: 使用 smoothDamp 避免"跳跃"4. Hermite vs 线性插值
Section titled “4. Hermite vs 线性插值”线性插值: 简单,但转向时不够平滑Hermite 插值: 使用速度信息,曲线更自然推荐: 对远程玩家使用 Hermite 插值