// Update function, called once per frame. Records the current inputs, and // occasionally physics + position data, to compensate for floating point drift. public void Update(PlayerController playerBall, int timestamp) { // Only record before maximum frames of position data has been recorded. if (positionData.Count < maxRecords && inputData.Count < maxRecords) { InputControllers.BasePlayerController playerController = playerBall.inputController; if (timestamp % positionRecordInterval == 0) { Rigidbody rigidbody = playerBall.gameObject.GetComponent <Rigidbody>(); PositionDataEntry positionDataEntry = new PositionDataEntry( timestamp, rigidbody.position, rigidbody.rotation, rigidbody.velocity, rigidbody.angularVelocity); positionData.Add(positionDataEntry); } Vector2 playerInputVector = playerBall.inputController.GetInputVector(); if (previousPlayerInputVector != playerInputVector) { InputDataEntry inputDataEntry = new InputDataEntry(timestamp, playerInputVector); inputData.Add(inputDataEntry); previousPlayerInputVector = playerInputVector; } } }
// Update function, called once per frame. Records the current inputs, and // occasionally physics + position data, to compensate for floating point drift. public void Update(PlayerController playerBall, int timestamp) { InputControllers.BasePlayerController playerController = playerBall.inputController; if (timestamp % positionRecordFrequencyInHz == 0) { Rigidbody rigidbody = playerBall.gameObject.GetComponent <Rigidbody>(); PositionDataEntry positionDataEntry = new PositionDataEntry( timestamp, rigidbody.position, rigidbody.rotation, rigidbody.velocity, rigidbody.angularVelocity); positionData.Add(positionDataEntry); } Vector2 playerInputVector = playerBall.inputController.GetInputVector(); if (previousPlayerInputVector != playerInputVector) { InputDataEntry inputDataEntry = new InputDataEntry(timestamp, playerInputVector); inputData.Add(inputDataEntry); previousPlayerInputVector = playerInputVector; } }
// Update the current GameObject position and rotation in fixed framerate if in playing state. void FixedUpdate() { if (replayData != null && animState == AnimState.Playing) { // Move positionDataIndex so that the timestamp of current positionEntry is greater or // equal to current time stamp. while (positionDataIndex < replayData.positionData.Length && replayData.positionData[positionDataIndex].timestamp < timestamp) { positionDataIndex++; } if (positionDataIndex < replayData.positionData.Length) { PositionDataEntry entry = replayData.positionData[positionDataIndex]; if (positionDataIndex == 0 || entry.timestamp == timestamp) { transform.position = entry.position; transform.rotation = entry.rotation; } else { // Interpolate position/rotation based on two recorded frames PositionDataEntry startEntry = replayData.positionData[positionDataIndex - 1]; float fT = (float)(timestamp - startEntry.timestamp) / (float)(entry.timestamp - startEntry.timestamp); transform.position = Vector3.Lerp(startEntry.position, entry.position, fT); transform.rotation = Quaternion.Slerp(startEntry.rotation, entry.rotation, fT); } ++timestamp; } else { if (shouldLoop) { // Loop back to first frame timestamp = 0; positionDataIndex = 0; } else { animState = AnimState.Finished; if (finishEvent != null) { finishEvent.Invoke(); } } } } }