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}");
            }
        }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 3
0
        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();
        }
Exemplo n.º 4
0
        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();
        }