Example #1
0
        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;
        }
Example #2
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();
        }