with one click
game-netcode
写多人/联网游戏时使用。同步模型、延迟、断线、防作弊。
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
写多人/联网游戏时使用。同步模型、延迟、断线、防作弊。
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
做 Cocos Creator 多机型/多分辨率适配时使用。Canvas、Widget、安全区。
Cocos Creator 用 AssetBundle 做分包/远程资源时使用。加载、释放、依赖、缓存。
优化 Cocos Creator 渲染性能时使用。合批、图集、动静分离、Label。
给 Cocos Creator 原生包做热更新时使用。version manifest、增量、校验、回滚。
写 Cocos Creator 动效/动画时使用。tween、Animation、Spine、性能与清理。
做 Cocos Creator 大量条目列表时使用。虚拟列表、节点复用。
| name | game-netcode |
| description | 写多人/联网游戏时使用。同步模型、延迟、断线、防作弊。 |
| category | gamedev |
| tags | ["网络","同步","多人"] |
规则: 按游戏类型明确选择状态同步或帧同步,并在立项初期确定好权威端,后期切换代价极高。
为什么: 常见错误是用帧同步做 MMORPG——每帧广播全量输入,稍有延迟就全员卡顿;或者在格斗/RTS 里用状态同步,服务端每帧推送全局状态,带宽爆炸且客户端表现割裂。更隐蔽的错误是"临时先客户端权威,后面再改",结果权威端逻辑散落到客户端每个角落,迁移时要全局重写。
怎么做:
规则: 伤害计算、金币增减、技能命中判定等影响游戏公平性的逻辑必须在服务端执行并校验,客户端只负责表现与预测,不能只靠客户端上报结果。
为什么: 最常犯的错是"客户端算出伤害 150,发消息给服务端说'我打了 150 伤害',服务端直接扣血"。这是最经典的游戏外挂入口——改一行本地代码就能无限秒杀。即使是"只是 Demo"也会留下习惯,真正上线时来不及改。
怎么做:
MsgAttack{target_id, skill_id, client_tick}),服务端收到后自己算伤害、自己扣血、再广播结果。规则: 客户端必须做本地预测(降低操作延迟感),服务端必须做状态校正(保证一致性),远端实体必须做插值(消除抖动),三者缺一不可。
为什么: 只做预测不做校正,高延迟玩家的角色会在服务端和客户端持续撕裂,最终位置对不上;只做插值不做预测,玩家按下跳跃键需要一个 RTT 才能看到角色起跳,手感极差;什么都不做,100ms 延迟就已经让动作游戏完全不可玩。
怎么做:
// 客户端预测:立刻在本地执行输入
void OnPlayerInput(InputCmd cmd) {
ApplyInputLocally(cmd); // 立刻移动本地角色
pendingInputs.push_back(cmd); // 暂存等服务端确认
SendToServer(cmd);
}
// 服务端 ACK 后做 Reconciliation
void OnServerState(ServerSnapshot snap) {
// 回滚到 snap.tick 时刻,重放 snap.tick 之后的本地输入
RollbackTo(snap);
for (auto& cmd : pendingInputs) {
if (cmd.tick > snap.tick) ApplyInputLocally(cmd);
}
}
// 远端实体插值(不是本地玩家)
void UpdateRemoteEntity(float deltaTime) {
renderPos = Vector3.Lerp(renderPos, authorativePos, deltaTime * lerpSpeed);
}
规则: 网络游戏必须将断线重连作为一等功能设计,而不是事后补丁。服务端状态快照可随时还原,消息处理天然幂等,重连后能补全缺失的帧/事件。
为什么: 最常见的事故:断线重连成功,但服务端已经销毁了该玩家的战斗实体,客户端收到空数据崩溃;或者消息重发时,金币被加了两次——因为消息处理没有去重逻辑。另一个坑:帧同步游戏断线后无法快速追帧,重连要从第 0 帧开始 replay,追帧期间玩家干等几分钟。
怎么做:
msg_id,服务端去重表(TTL 5 分钟)防止重放。规则: 同步数据必须做增量差分、字段量化、AOI(Area of Interest)裁剪;同步频率按实体重要性分级,不对所有实体以最高频率广播全量状态。
为什么: 最常见的性能炸弹:100 个玩家的游戏,每帧把 100 个玩家的全量状态(位置、HP、所有 buff)广播给所有人——带宽是 O(N²) 的。50 个玩家时服务器还扛得住,200 人时直接打满带宽。量化(Quantization)也经常被忽略:用 float32 传位置精度远超需求,用 int16 传量化坐标可以砍掉一半带宽。
怎么做:
# 反例 — 客户端计算完伤害直接告诉服务端"扣多少血"
# client.py
damage = calc_damage_locally(my_atk, target_def) # 本地算
send_to_server({"type": "deal_damage", "target": enemy_id, "amount": damage}) # ❌ 外挂改这一行
# server.py
def on_deal_damage(msg):
target = get_entity(msg["target"])
target.hp -= msg["amount"] # ❌ 直接信任客户端上报的数值
broadcast_hp_update(target)
# 正例 — 客户端只发意图,服务端自己算伤害
# client.py
send_to_server({"type": "attack", "target": enemy_id, "skill": skill_id, "tick": local_tick}) # ✅ 只发意图
# server.py
def on_attack(msg, attacker):
target = get_entity(msg["target"])
skill = get_skill(msg["skill"])
# 服务端用权威数据计算
damage = calc_damage(attacker.atk, target.def_, skill.multiplier) # ✅ 服务端自己算
target.hp -= damage
broadcast_hp_update(target)
# 反例 — 每个 Tick 给每个玩家发所有实体的全量数据
def game_tick():
all_state = serialize_all_entities() # ❌ 全量,可能是几十 KB
for player in all_players:
player.send(all_state) # ❌ O(N²) 广播
# 正例 — 增量 + AOI 裁剪
def game_tick():
for player in all_players:
nearby = get_entities_in_aoi(player.pos, radius=150) # ✅ AOI 裁剪
delta = serialize_dirty_fields(nearby, since=player.last_ack_tick) # ✅ 只发变更字段
if delta:
player.send(delta)
player.last_ack_tick = current_tick