void ServerUpdate() { while (_serverPredictedMessageBuffer.Count > 0 && _networkClock.CurrentTime >= _serverPredictedMessageBuffer.Peek().Element.deliveryTime) { ClientPredictedMessage clientPredictedMessage = _serverPredictedMessageBuffer.Dequeue().Element; // message contains an array of inputs, calculate what tick the final one is uint maxTick = clientPredictedMessage.startTickNumber + (uint)clientPredictedMessage.inputs.Length - 1; // if that tick is greater than or equal to the current tick we're on, then it // has inputs which are new if (maxTick >= _currentTickNumber) { // there may be some inputs in the array that we've already had, // so figure out where to start uint startIndex = _currentTickNumber > clientPredictedMessage.startTickNumber ? (_currentTickNumber - clientPredictedMessage.startTickNumber) : 0; // run through all relevant inputs, and step player forward for (int i = (int)startIndex; i < clientPredictedMessage.inputs.Length; ++i) { _currentTickNumber++; InputProcessorComponent.ExecuteInputs(clientPredictedMessage.inputs[i]); } } } }
void ClientUpdate() { _clientTimer += Time.deltaTime; while (_clientTimer >= Time.fixedDeltaTime) { _clientTimer -= Time.deltaTime; uint bufferSlot = _currentTickNumber % _clientBufferSize; _clientInputBuffer[bufferSlot] = InputProcessorComponent.GetCurrentInputs(); // store state for this tick, then use current state + input to step simulation ClientStoreCurrentStateAndStep(ref _clientStateBuffer[bufferSlot], InputProcessorComponent.GetCurrentInputs()); ClientPredictedMessage clientPredictedMessage = new ClientPredictedMessage(); clientPredictedMessage.packetId = _clientPacketID; clientPredictedMessage.deliveryTime = _networkClock.CurrentTime; clientPredictedMessage.startTickNumber = _sendRedundantInputsToServer ? _clientLastReceivedStateTickNumber : _currentTickNumber; var inputList = new List <Inputs>(); for (uint tick = clientPredictedMessage.startTickNumber; tick <= _currentTickNumber; tick++) { inputList.Add(_clientInputBuffer[tick % _clientBufferSize]); } clientPredictedMessage.inputs = inputList.ToArray(); //Send Input Message To Server connectionToServer.Send(_predictedMessageReceivedID, clientPredictedMessage); _clientPacketID++; _currentTickNumber++; } if (ClientHasStateMessage()) { ServerStateMessage serverStateMessage = _clientServerStateMessageBuffer.Dequeue().Element; while (ClientHasStateMessage() ) // make sure if there are any newer state messages available, we use those instead { serverStateMessage = _clientServerStateMessageBuffer.Dequeue().Element; } _clientLastReceivedStateTickNumber = serverStateMessage.tickNumber; //Broadcast this server state for easy access for debugging purposes if (OnValidSercerStateReceived != null) { OnValidSercerStateReceived(serverStateMessage.serverState); } //----------------------------- uint bufferSlot = serverStateMessage.tickNumber % _clientBufferSize; Vector3 positionError = serverStateMessage.serverState.position - _clientStateBuffer[bufferSlot].position; float rotationError = 1.0f - Quaternion.Dot(serverStateMessage.serverState.rotation, _clientStateBuffer[bufferSlot].rotation); //Validating position,rotation and extras rules defined in de State processor if (positionError.sqrMagnitude > 0.0000001f || rotationError > 0.00001f || !StateProcessorComponent.IsValidateState(ref serverStateMessage.serverState, ref _clientStateBuffer[bufferSlot])) { ApplyCorrectionsWithServerState(serverStateMessage, bufferSlot); } } SmoothTransformForModels(); }