跳转到内容

网络同步系统 (Network)

@esengine/network 提供基于 @esengine/rpc 的类型安全网络同步解决方案,用于多人游戏的实体同步、输入处理和状态插值。

网络模块由两个核心包组成:

包名描述
@esengine/rpc类型安全的 RPC 通信库
@esengine/network基于 RPC 的游戏网络插件
Terminal window
npm install @esengine/network

@esengine/rpc 会作为依赖自动安装。

客户端 服务器
┌────────────────────┐ ┌────────────────┐
│ NetworkPlugin │◄── WS ───►│ RpcServer │
│ ├─ NetworkService │ │ ├─ Protocol │
│ ├─ SyncSystem │ │ └─ Handlers │
│ ├─ SpawnSystem │ └────────────────┘
│ └─ InputSystem │
└────────────────────┘
import { Core, Scene } from '@esengine/ecs-framework';
import { NetworkPlugin, NetworkIdentity, NetworkTransform } from '@esengine/network';
// 定义游戏场景
class GameScene extends Scene {
initialize(): void {
this.name = 'Game';
}
}
// 初始化
Core.create({ debug: false });
const scene = new GameScene();
Core.setScene(scene);
// 安装网络插件
const networkPlugin = new NetworkPlugin();
await Core.installPlugin(networkPlugin);
// 注册预制体工厂
networkPlugin.registerPrefab('player', (scene, spawn) => {
const entity = scene.createEntity(`player_${spawn.netId}`);
const identity = entity.addComponent(new NetworkIdentity());
identity.netId = spawn.netId;
identity.ownerId = spawn.ownerId;
identity.bIsLocalPlayer = spawn.ownerId === networkPlugin.localPlayerId;
entity.addComponent(new NetworkTransform());
return entity;
});
// 连接服务器
const success = await networkPlugin.connect({
url: 'ws://localhost:3000',
playerName: 'Player1',
roomId: 'room-1' // 可选
});
if (success) {
console.log('Connected! Player ID:', networkPlugin.localPlayerId);
}
import { RpcServer } from '@esengine/rpc/server';
import { gameProtocol } from '@esengine/network';
const server = new RpcServer(gameProtocol, {
port: 3000,
onStart: (port) => console.log(`Server running on ws://localhost:${port}`)
});
// 注册 API 处理器
server.handle('join', async (input, ctx) => {
const playerId = generatePlayerId();
return { playerId, roomId: input.roomId ?? 'default' };
});
server.handle('leave', async (input, ctx) => {
// 处理玩家离开
});
await server.start();

你可以基于 @esengine/rpc 定义自己的协议:

import { rpc } from '@esengine/rpc';
// 定义自定义协议
export const myProtocol = rpc.define({
api: {
login: rpc.api<{ username: string }, { token: string }>(),
getData: rpc.api<{ id: number }, { data: object }>(),
},
msg: {
chat: rpc.msg<{ from: string; text: string }>(),
notification: rpc.msg<{ type: string; content: string }>(),
},
});
// 使用自定义协议创建服务
import { RpcService } from '@esengine/network';
const service = new RpcService(myProtocol);
await service.connect({ url: 'ws://localhost:3000' });
// 类型安全的 API 调用
const result = await service.call('login', { username: 'test' });
console.log(result.token);
// 类型安全的消息监听
service.on('chat', (data) => {
console.log(`${data.from}: ${data.text}`);
});

用于依赖注入:

import {
NetworkServiceToken,
NetworkSyncSystemToken,
NetworkSpawnSystemToken,
NetworkInputSystemToken,
NetworkPredictionSystemToken,
NetworkAOISystemToken,
} from '@esengine/network';
const networkService = services.get(NetworkServiceToken);
const predictionSystem = services.get(NetworkPredictionSystemToken);
const aoiSystem = services.get(NetworkAOISystemToken);

网络模块提供可视化脚本支持:

  • IsLocalPlayer - 检查实体是否为本地玩家
  • IsServer - 检查是否运行在服务器端
  • HasAuthority - 检查是否有权限控制实体
  • GetNetworkId - 获取实体的网络 ID
  • GetLocalPlayerId - 获取本地玩家 ID