void Update()
{
double currentTime = Network.time;
double interpolationTime = currentTime - interpolationBackTime;
// We have a window of interpolationBackTime where we basically play
// By having interpolationBackTime the average ping, you will usually use interpolation.
// And only if no more data arrives we will use extrapolation
// Use interpolation
// Check if latest state exceeds interpolation time, if this is the case then
// it is too old and extrapolation should be used
if (m_BufferedState[0].timestamp > interpolationTime) {
for (int i = 0; i < m_TimestampCount; i++) {
// Find the state which matches the interpolation time (time+0.1) or use last state
if (m_BufferedState[i].timestamp <= interpolationTime || i == m_TimestampCount - 1) {
// The state one slot newer (<100ms) than the best playback state
State rhs = m_BufferedState[Mathf.Max (i - 1, 0)];
// The best playback state (closest to 100 ms old (default time))
State lhs = m_BufferedState[i];
// Use the time between the two slots to determine if interpolation is necessary
double length = rhs.timestamp - lhs.timestamp;
float t = 0.0f;
// As the time difference gets closer to 100 ms t gets closer to 1 in
// which case rhs is only used
if (length > 0.0001)
t = (float)((interpolationTime - lhs.timestamp) / length);
// if t=0 => lhs is used directly
transform.localPosition = Vector3.Lerp (lhs.pos, rhs.pos, t);
transform.localRotation = Quaternion.Slerp (lhs.rot, rhs.rot, t);
return;
}
}
// Use extrapolation. Here we do something really simple and just repeat the last
// received state. You can do clever stuff with predicting what should happen.
} else {
State latest = m_BufferedState[0];
transform.localPosition = latest.pos;
transform.localRotation = latest.rot;
}
}