资讯详情

资讯详情

ET帧同步的三个核心问题:预测、哈希校验与缺包补齐

ET帧同步的三个核心问题预测、哈希校验与缺包补齐【免费下载链接】ETUnity3D Client And C# Server Framework项目地址: https://gitcode.com/GitHub_Trending/et/ET帧同步Frame Sync只同步输入、不同步状态是竞技类多人游戏的经典方案。但真实网络环境里丢包、延迟、设备性能差异不可避免如何让所有客户端画面一致是 ET 框架的 lockstep 包早就拆好的一套实现。 两人同时按下攻击键为什么结果会不一样1V1 竞技中两名玩家在同一逻辑帧按下攻击键。由于延迟A 的客户端里 B 还没出手A 先挥出了剑B 的客户端看到的却是另一个画面。不解决同一份输入序列在所有机器上必须得到同一结果这件事击杀瞬间两边画面会分叉玩家报一次不同步这局就没法打了。核心原理只传输入其余重算帧同步的核心像合唱团看同一份总谱传输的数据只有每一帧的动作输入只要大家从同一个初始状态起步演出来的结果一定一致。以一整帧的完整流程为例执行链路是客户端 A 按键产生一帧输入发给房间房间收齐或补齐该帧所有玩家的输入把完整输入广播给全部客户端每个客户端用这份完整输入执行该帧帧计数 1客户端不等广播本地输入先预测执行最多领先权威帧 5 帧确认帧的输入到达后与预测不一致时从快照恢复世界、重新执行——这就是预测回滚。两个计数器预测帧与权威帧Room 实体持有两个计数权威帧AuthorityFrame服务器确认到的最新帧和预测帧PredictionFrame屏幕上实际执行到的帧。两者之差就是欠网络的债差得越大来包后要回滚的距离越长。哈希校验不靠自觉每帧执行完客户端把世界序列化字节算出哈希发给房间房间比对权威哈希不一致就下发 CheckHashFail客户端重连或回放重同步。静默分叉一帧内就能被发现。实现一张五个角色的模块地图模块位置职责RoomModel/Share帧状态机持有两个帧计数器FrameBufferModel/Share环形缓冲缓存每帧输入、世界快照与哈希FixedTimeCounterModel/Share固定步长计数把墙钟时间换算成帧号LSClientUpdaterSystemHotfix/Client客户端预测循环LSServerUpdaterSystemHotfix/Server服务器收输入、补包、广播完整结构见 核心模型 目录。客户端预测循环是核心// LSClientUpdaterSystem.Update简化骨架 while (true) { if (timeNow room.FixedTimeCounter.FrameTime(room.PredictionFrame 1)) return; // 还没到这一帧的固定时间 if (room.PredictionFrame - room.AuthorityFrame 5) return; // 预测最多领先权威帧 5 帧 room.PredictionFrame; var inputs self.GetOneFrameMessages(room.PredictionFrame); // inputs 上一确认帧里其他玩家的输入 本地输入 room.Update(inputs); // 执行本帧内部保存世界快照 room.SendHash(room.PredictionFrame); // 把本帧哈希发给房间 root.GetComponentClientSenderComponent().Send(frameMessage); // 发送本地输入 }服务器端只做收、补、广播三件事// LSServerUpdaterSystem.Update简化骨架 OneFrameInputs inputs frameBuffer.FrameInputs(frame); foreach (long playerId in room.PlayerIds) { if (inputs.Inputs.ContainsKey(playerId)) continue; // 输入没到用上一帧输入补齐没有上一帧就留空 inputs.Inputs[playerId] preFrameInput ?? new LSInput(); } RoomMessageHelper.BroadCast(room, inputs); // 完整输入广播给所有人 room.Update(inputs); // 服务器自己也推进一帧回放 LSReplayUpdater 走的是另一条路按 1 倍/8 倍速回放 Replay 里记录的输入与实盘共用同一个执行入口。 调优四个可落地的调优点固定步长用 50ms别用 16ms问题60fps 同步意味着服务器广播频率和哈希计算都翻倍丢包率随之上升。原因仓库里LSConstValue.UpdateInterval 50即每秒20个逻辑帧。做法逻辑帧率与渲染帧率解耦表现层动画、相机单独插值。预测帧上限锁死在 5问题玩家网络抖动 2 秒预测不限的话来包时要回滚 40 帧。做法PredictionFrame - AuthorityFrame 5时直接 return 等待用 SpeedMultiply 让表现层追帧宁可卡一下不重算一大段。缺输入就用上一帧补齐问题某玩家某一帧的输入包丢了严格帧同步会让全房间卡死等待。做法服务器拿他上一帧输入顶替没有上一帧就留空即使造成一帧偏差哈希校验也会发现。哈希每帧记完整快照 60 秒才存档问题每帧存一次完整快照内存吃不消。原因FrameBuffer 的快照环形缓冲只服务回滚Replay 的长期存档只为了回放。做法Record 每帧记录输入完整世界每 60×20 帧才序列化一次。 五步验证路径克隆仓库git clone https://gitcode.com/GitHub_Trending/et/ET按 运行指南 打开 Unity 工程启动服务端与客户端。在 demo 中发起匹配观察 Gate → Match → Map → Room 的纤程创建FiberInit_Match、FiberInit_Map 等房间在 Room 纤程内建立。观察哈希校验每帧客户端上报哈希C2Room_CheckHashHandler房间广播权威输入不一致时收到 Room2C_CheckHashFailHandler 触发重同步。用 机器人包 补位其余玩家验证多输入收集与补包逻辑。![ET帧同步demo加载场景](https://raw.gitcode.com/GitHub_Trending/et/ET/raw/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.lockstep/Assets/GameRes/Loading/Sprites/Warrior_Background2 1.png?utm_sourcegitcode_repo_files) 值得继续深挖的两个方向回滚与快照恢复的细节在 cn.etetet.truesync 的 TrueSync 执行引擎里多房间与规模化部署看 actor location 包动手验证从 运行指南 开始。【免费下载链接】ETUnity3D Client And C# Server Framework项目地址: https://gitcode.com/GitHub_Trending/et/ET创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →