private void FillInputWithLastFrame(ServerFrame frame) { int tick = frame.tick; var inputs = frame.Inputs; var lastFrameInputs = tick == 0 ? null : cmdBuffer.GetFrame(tick - 1)?.Inputs; var curFrameInput = inputs[_localActorId]; //将所有角色 给予默认的输入 for (int i = 0; i < _actorCount; i++) { inputs[i] = new Msg_PlayerInput(tick, _allActors[i], lastFrameInputs?[i]?.Commands?.ToList()); } inputs[_localActorId] = curFrameInput; }
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(); }