public IEnumerator CheckMultipleInputCorrection() { //Setup RollbackManager with the input manager if (RollbackManager.Instance.GetComponent <SampleRollbackInputManager>() == null) { RollbackManager.Instance.gameObject.AddComponent <SampleRollbackInputManager>(); RollbackManager.Instance.ResetRbInputManagerEvents(); } RollbackManager.Instance.bufferSize = -1; RollbackManager.Instance.bufferRestriction = false; RollbackManager.Instance.registerFrames = false; RollbackManager.Instance.ClearRollbackManager(); Assert.True(RollbackManager.Instance.GetDisplayedFrameNum() == 0); Assert.True(RollbackManager.Instance.GetMaxFramesNum() == 0); int playerId = RollbackManager.rbInputManager.AddPlayer(); yield return(new WaitForSeconds(0.1f)); RollbackManager.Instance.Simulate(NumFramesToSimulate); Assert.True(RollbackManager.Instance.GetDisplayedFrameNum() == NumFramesToSimulate); yield return(new WaitForSeconds(0.1f)); //Correct input of a certain frame number RollbackElementRollbackInputBaseActions playerInputHistory = RollbackManager.rbInputManager.GetPlayerInputHistory(playerId); RollbackInputBaseActions rbInput = new RollbackInputBaseActions(5); rbInput.SetHorizontalAxis(1.0f); rbInput.SetVerticalAxis(1.0f); rbInput.SetBit(3); for (int i = 1; i < RollbackManager.Instance.GetDisplayedFrameNum(); i++) { Assert.True(playerInputHistory.CorrectValue(rbInput, i)); } //Resimulate frames yield return(new WaitForSeconds(0.1f)); RollbackManager.Instance.ReSimulate(NumFramesToSimulate); yield return(new WaitForSeconds(0.1f)); //Get corrected input for (int i = 1; i < RollbackManager.Instance.GetDisplayedFrameNum(); i++) { RollbackInputBaseActions rbCorrectedInput = RollbackManager.rbInputManager.GetPlayerInputHistory(playerId).GetValue(i); Assert.True(rbCorrectedInput.Equals(rbInput)); Assert.True(Math.Abs(rbCorrectedInput.GetHorizontalAxis() - 1.0f) < 0.001f); } }
/// <summary>Creates the "custom content" Hashtable that is sent as position update.</summary> /// <remarks> /// As with event codes, the content of this event is arbitrary and "made up" for this demo. /// Your game (e.g.) could use floats as positions or you send a height and actions or state info. /// It makes sense to use numbers (best: bytes) as Hashtable key type, cause they are use less space. /// But this is not a requirement as you see in WriteEvColor. /// /// The position can only go up to 128 in this demo, so a byte[] technically is the best (leanest) /// choice here. /// </remarks> /// <returns>Hashtable for event "move" to update others</returns> public Hashtable WriteEvInput() { Hashtable evContent = new Hashtable(); int currentFrameNum = RollbackManager.Instance.GetIndexFrameNumFromStart(); int numFramesToSend = CustomConstants.NetworkBufferSize; if (numFramesToSend >= currentFrameNum) { numFramesToSend = currentFrameNum - 1; } evContent[0] = numFramesToSend; // Last x frames to pass through the evContent[1] = currentFrameNum; // Current frame number RollbackElementRollbackInputBaseActions playerInputHistory = RollbackManager.rbInputManager.GetPlayerInputHistory(ActorNumber - 1); for (int i = 0; i < numFramesToSend; i++) { RollbackInputBaseActions rollbackInputBaseActions = playerInputHistory.GetValue(currentFrameNum - i); evContent[2 + i] = rollbackInputBaseActions.PackBits(); } return(evContent); }
/// <summary>Reads the "custom content" Hashtable that is sent as position update.</summary> /// <returns>Hashtable for event "move" to update others</returns> public void ReadEvInput(Hashtable evContent) { int numFramesReceived = 0; if (evContent.ContainsKey((int)0)) { numFramesReceived = (int)evContent[0]; } if (numFramesReceived <= 0) { return; } int sentAtFrameNumber = 0; int currentFrame = RollbackManager.Instance.GetIndexFrameNumFromStart(); if (evContent.ContainsKey((int)1)) { sentAtFrameNumber = (int)evContent[1]; } int numDiffFramesWithPresent = currentFrame - sentAtFrameNumber; int applicableFrame = RollbackManager.Instance.GetMaxFramesNum() - numDiffFramesWithPresent; RollbackElementRollbackInputBaseActions playerInputHistory = RollbackManager.rbInputManager.GetPlayerInputHistory(ActorNumber - 1); //Correct inputs int backtrackNumFrames = -1; for (int i = 0; i < numFramesReceived; i++) { if (LastConfirmedFrame >= sentAtFrameNumber - i) { break; } RollbackInputBaseActions baseActions = new RollbackInputBaseActions(); baseActions.UnpackBits((byte[])evContent[2 + i]); //If return true, that means the correction was done if (playerInputHistory.CorrectValue(baseActions, applicableFrame - i)) { backtrackNumFrames = i + 1; } } // If at least a frame changed, we make a simulate if (backtrackNumFrames > -1) { //Predict new inputs from difference of receiving RollbackInputBaseActions lastInput = new RollbackInputBaseActions(); lastInput.UnpackBits((byte[])evContent[2]); // The latest frame is always on 2 for (int i = 0; i < numDiffFramesWithPresent; i++) { playerInputHistory.CorrectValue(lastInput, applicableFrame + i); } //Resimulate actions depending RollbackManager.Instance.ReSimulate(backtrackNumFrames + numDiffFramesWithPresent + 5); } this.LastConfirmedFrame = sentAtFrameNumber; this.LastUpdateFrame = GameLogic.Timestamp; }