private void RollbackTo(int tick, int maxContinueServerTick, bool isNeedClear = true) { _world.RollbackTo(tick, maxContinueServerTick, isNeedClear); var hash = _commonStateService.Hash; var curHash = _hashHelper.CalcHash(); if (hash != curHash) { Debug.LogError($"Rollback error: Hash isDiff oldHash ={hash} curHash{curHash}"); } }
private bool RollbackTo(int tick, int maxContinueServerTick, bool isNeedClear = true) { _world.RollbackTo(tick, maxContinueServerTick, isNeedClear); var hash = _commonStateService.Hash; var curHash = _hashHelper.CalcHash(); if (hash != curHash) { Debug.LogError($"tick:{tick} Rollback error: Hash isDiff oldHash ={hash} curHash{curHash}"); #if UNITY_EDITOR _dumpHelper.DumpToFile(true); return(false); #endif } return(true); }
public override void DoUpdate(float deltaTime) { if (!Running) { return; } if (_constStateService.IsVideoMode) { return; } cmdBuffer.Ping = _networkService.Ping; cmdBuffer.UpdateFramesInfo(); var missFrameTick = cmdBuffer.GetMissServerFrameTick(); //客户端落后服务器太多帧 请求丢失帧 if (cmdBuffer.IsNeedReqMissFrame()) { _networkService.SendMissFrameReq(missFrameTick); } //if (!cmdBuffer.CanExecuteNextFrame()) { //因为网络问题 需要等待服务器发送确认包 才能继续往前 // return; //} _frameDeadline = Time.realtimeSinceStartup + MaxSimulationMsPerFrame; var minTickToBackup = missFrameTick - FrameBuffer.SnapshotFrameInterval; //追帧 无输入 _constStateService.isPursueFrame = true; if (!PursueServer(minTickToBackup)) { _constStateService.isPursueFrame = false; Debug.Log($"PurchaseServering curTick:" + _world.Tick); return; } _constStateService.isPursueFrame = false; var frameDeltaTime = (Time.realtimeSinceStartup - timestampOnPurcue) * 1000; var targetTick = Mathf.CeilToInt(frameDeltaTime / NetworkDefine.UPDATE_DELTATIME) + tickOnPursue; //正常跑帧 while (_world.Tick < targetTick) { var curTick = _world.Tick; cmdBuffer.UpdateFramesInfo(); //校验服务器包 如果有预测失败 则需要进行回滚 if (cmdBuffer.IsNeedRevert) { _world.RollbackTo(cmdBuffer.nextTickToCheck, missFrameTick); _world.CleanUselessSnapshot(System.Math.Min(cmdBuffer.nextTickToCheck - 1, _world.Tick)); minTickToBackup = System.Math.Max(minTickToBackup, _world.Tick + 1); while (_world.Tick < missFrameTick) { var sFrame = cmdBuffer.GetServerFrame(_world.Tick); Logging.Debug.Assert(sFrame != null && sFrame.tick == _world.Tick, $" logic error: server Frame must exist tick {_world.Tick}"); //服务器超前 客户端 应该追上去 将服务器中的输入作为客户端输入 cmdBuffer.PushLocalFrame(sFrame); Simulate(sFrame, _world.Tick >= minTickToBackup); } while (_world.Tick < curTick) { var frame = cmdBuffer.GetLocalFrame(_world.Tick); FillInputWithLastFrame(frame); //加上输入预判 减少回滚 Logging.Debug.Assert(frame != null && frame.tick == _world.Tick, $" logic error: local frame must exist tick {_world.Tick}"); Predict(frame, _world.Tick > minTickToBackup); } } { if (_world.Tick == curTick) //当前帧 没有被执行 需要执行之 { ServerFrame cFrame = null; var sFrame = cmdBuffer.GetServerFrame(_world.Tick); if (sFrame != null) { cFrame = sFrame; } else { var input = new Msg_PlayerInput(curTick, _localActorId, _inputService.GetInputCmds()); cFrame = new ServerFrame(); var inputs = new Msg_PlayerInput[_actorCount]; inputs[_localActorId] = input; cFrame.Inputs = inputs; cFrame.tick = curTick; FillInputWithLastFrame(cFrame); #if DEBUG_FRAME_DELAY input.timeSinceStartUp = Time.realtimeSinceStartup; #endif if (curTick > cmdBuffer.maxServerTickInBuffer) //服务器的输入还没到 需要同步输入到服务器 { SendInput(input); } } cmdBuffer.PushLocalFrame(cFrame); Predict(cFrame); } } } //end of while(_world.Tick < targetTick) CheckAndSendHashCodes(); }
private void Step() { if (_constStateService.IsClientMode) { var input = new Msg_PlayerInput(_world.Tick, _localActorId, _inputService.GetInputCmds()); var frame = new ServerFrame() { tick = _world.Tick, _inputs = new Msg_PlayerInput[] { input } }; _cmdBuffer.PushLocalFrame(frame); _cmdBuffer.PushServerFrames(new ServerFrame[] { frame }); _cmdBuffer.UpdateFramesInfo(); Simulate(_cmdBuffer.GetFrame(_world.Tick)); return; } //cmdBuffer.Ping = _gameMsgService.Ping; _cmdBuffer.UpdateFramesInfo(); var missFrameTick = _cmdBuffer.GetMissServerFrameTick(); //客户端落后服务器太多帧 请求丢失帧 if (_cmdBuffer.IsNeedReqMissFrame()) { _networkService.SendMissFrameReq(missFrameTick); } //if (!cmdBuffer.CanExecuteNextFrame()) { //因为网络问题 需要等待服务器发送确认包 才能继续往前 // return; //} _frameDeadline = LTime.realtimeSinceStartup + MaxSimulationMsPerFrame; var minTickToBackup = missFrameTick - FrameBuffer.SnapshotFrameInterval; //追帧 无输入 var isPursueServer = !PursueServer(minTickToBackup); if (isPursueServer) { _constStateService.IsPursueFrame = true; Debug.Log($"PurchaseServering curTick:" + _world.Tick); EventHelper.Trigger(EEvent.PursueFrameProcess, GetPursueProgress()); return; } if (_constStateService.IsPursueFrame) { EventHelper.Trigger(EEvent.PursueFrameDone); } _constStateService.IsPursueFrame = false; var frameDeltaTime = (LTime.realtimeSinceStartup - _timestampOnPurcue) * 1000; var targetTick = (float)System.Math.Ceiling(frameDeltaTime / NetworkDefine.UPDATE_DELTATIME) + _tickOnPursue; //正常跑帧 while (_world.Tick < targetTick) { var curTick = _world.Tick; _cmdBuffer.UpdateFramesInfo(); //校验服务器包 如果有预测失败 则需要进行回滚 if (_cmdBuffer.IsNeedRollback) { _world.RollbackTo(_cmdBuffer.nextTickToCheck, missFrameTick); _world.CleanUselessSnapshot(System.Math.Min(_cmdBuffer.nextTickToCheck - 1, _world.Tick)); minTickToBackup = System.Math.Max(minTickToBackup, _world.Tick + 1); while (_world.Tick < missFrameTick) { var sFrame = _cmdBuffer.GetServerFrame(_world.Tick); Logging.Debug.Assert(sFrame != null && sFrame.tick == _world.Tick, $" logic error: server Frame must exist tick {_world.Tick}"); //服务器超前 客户端 应该追上去 将服务器中的输入作为客户端输入 _cmdBuffer.PushLocalFrame(sFrame); Simulate(sFrame, _world.Tick >= minTickToBackup); } while (_world.Tick < curTick) { var frame = _cmdBuffer.GetLocalFrame(_world.Tick); FillInputWithLastFrame(frame); //加上输入预判 减少回滚 Logging.Debug.Assert(frame != null && frame.tick == _world.Tick, $" logic error: local frame must exist tick {_world.Tick}"); Predict(frame, _world.Tick > minTickToBackup); } } { if (_world.Tick == curTick) //当前帧 没有被执行 需要执行之 { ServerFrame cFrame = null; var sFrame = _cmdBuffer.GetServerFrame(_world.Tick); if (sFrame != null) { cFrame = sFrame; } else { var input = new Msg_PlayerInput(curTick, _localActorId, _inputService.GetInputCmds()); cFrame = new ServerFrame(); var inputs = new Msg_PlayerInput[_actorCount]; inputs[_localActorId] = input; cFrame.Inputs = inputs; cFrame.tick = curTick; FillInputWithLastFrame(cFrame); if (curTick > _cmdBuffer.maxServerTickInBuffer) //服务器的输入还没到 需要同步输入到服务器 { SendInput(input); } } _cmdBuffer.PushLocalFrame(cFrame); Predict(cFrame); } } } //end of while(_world.Tick < targetTick) CheckAndSendHashCodes(); }