ColyseusJS 多人游戏服务器状态管理与同步
状态管理与同步
Colyseus 是一个轻量级的多人游戏服务器框架,支持高效的客户端-服务器状态同步。本文主要介绍如何使用 Colyseus 的状态管理功能。
状态处理
在 Colyseus 中,每个房间都维护自己的状态,并且这些状态会自动同步到所有连接的客户端。
序列化方法
默认情况下,Colyseus 使用 Schema 作为序列化方法。以下是其工作原理:
- 当用户成功加入房间时,客户端会接收到完整的初始状态。
- 根据设置的
patchRate(默认 50ms),服务器会向客户端发送状态变化的二进制补丁。 - 客户端接收到补丁后,会触发
onStateChange方法。
Schema 结构
SchemaSerializer 是从 Colyseus 0.10 开始引入的默认序列化方式。以下是如何定义和使用 Schema:
import { Schema, type } from "@colyseus/schema";
class GameState extends Schema {
@type("string")
currentPlayer: string;
@type({ map: Player })
players = new MapSchema<Player>();
}
原始类型
您可以为 @type() 装饰器指定多种原始类型以优化序列化性能:
| Type | Description | Limitation |
|---|---|---|
| "string" | UTF-8 字符串 | 最大字节大小为 4294967295 |
| "int8" | 有符号 8 位整数 | -128 到 127 |
| "float32" | 单精度浮点数 | -3.40282347e+38 到 3.40282347e+38 |
集合类型
ArraySchema
ArraySchema 是可同步的数组版本,支持常见的数组操作:
class RoomState extends Schema {
@type([ "number" ])
numbers = new ArraySchema<number>();
addNumber(num) {
this.numbers.push(num);
}
removeLast() {
this.numbers.pop();
}
}
MapSchema
MapSchema 是可同步的映射表,适合按 ID 跟踪游戏实体:
class RoomState extends Schema {
@type({ map: Player })
playerMap = new MapSchema<Player>();
addPlayer(id, player) {
this.playerMap.set(id, player);
}
removePlayer(id) {
this.playerMap.delete(id);
}
}
数据过滤
通过 @filter() 和 @filterChildren(),可以实现对特定客户端隐藏部分状态的功能。
class Card extends Schema {
@type("string") owner: string;
@filter(function(this: Card, client, value, root) {
return this.owner === client.sessionId;
})
@type("uint8") number: number;
}
最佳实践
- 保持房间类尽可能小,避免直接包含游戏逻辑。
- 使用命令模式分离动作执行逻辑,便于扩展和测试。
安装与初始化
npm install --save @colyseus/command
import { Dispatcher } from "@colyseus/command";
class GameRoom extends Room {
dispatcher = new Dispatcher(this);
onJoin(client, options) {
this.dispatcher.dispatch(new JoinCommand(), { sessionId: client.sessionId });
}
}