void Update() { // is this the server? send out position updates every 1/10 second if (Network.isServer) { updateTimer += Time.deltaTime; if (updateTimer >= 0.1f) { updateTimer = 0f; networkView.RPC("netUpdate", RPCMode.Others, transform.position); } } if (networkView.isMine) { return; // don't run interpolation on the local object } if (stateCount == 0) { return; // no states to interpolate } double currentTime = Network.time; double interpolationTime = currentTime - InterpolationBackTime; // the latest packet is newer than interpolation time - we have enough packets to interpolate if (stateBuffer[0].Timestamp > interpolationTime) { for (int i = 0; i < stateCount; i++) { // find the closest state that matches network time, or use oldest state if (stateBuffer[i].Timestamp <= interpolationTime || i == stateCount - 1) { // the state closest to network time networkState lhs = stateBuffer[i]; // the state one slot newer networkState rhs = stateBuffer[Mathf.Max(i - 1, 0)]; // use time between lhs and rhs to interpolate double length = rhs.Timestamp - lhs.Timestamp; float t = 0f; if (length > 0.0001) { t = (float)((interpolationTime - lhs.Timestamp) / length); } transform.position = Vector3.Lerp(lhs.Position, rhs.Position, t); break; } } } }
int stateCount = 0; //how many states have been recorded #endregion Fields #region Methods //save new state to buffer void BufferState(networkState state) { //shift buffer contents to accomodate new state for (int i = stateBuffer.Length - 1; i > 0; i--) { stateBuffer[i] = stateBuffer[i - 1]; } //save state to slot 0 stateBuffer[0] = state; //increment state count (up to buffer size) stateCount = Mathf.Min(stateCount + 1, stateBuffer.Length); }
//save new state to buffer void BufferState(networkState state) { //shift buffer contents to accomodate new state for (int i = stateBuffer.Length - 1; i > 0; i--) { stateBuffer[i] = stateBuffer[i - 1]; } //save state to slot 0 stateBuffer[0] = state; //increment state count (up to buffer size) stateCount = Mathf.Min(stateCount + 1, stateBuffer.Length); }
int stateCount = 0; //how many states have been recorded void Update() { if (networkView.isMine) // don't run interpolation on local object { return; } if (stateCount == 0) // no states to interpolate { return; } double currentTime = Network.time; double interpolationTime = currentTime - interpolationBackTime; //if the latest packet is newer than interpolation time: //we have enough packets to interpolate if (stateBuffer[0].timeStamp > interpolationTime) { for (int i = 0; i < stateCount; i++) { //find the closest state that matches network time //or use oldest state if (stateBuffer[i].timeStamp <= interpolationTime || i == stateCount - 1) { //the state closest to network time networkState lhs = stateBuffer[i]; //the state one slot newer networkState rhs = stateBuffer[Mathf.Max(i - 1, 0)]; //use time between lhs and rhs to interpolate double length = rhs.timeStamp - lhs.timeStamp; float t = 0f; if (length > 0.0001) { t = (float)((interpolationTime - lhs.timeStamp) / length); } transform.position = Vector3.Lerp( lhs.position, rhs.position, t); break; } } } }
void bufferState(networkState state) { // shift states // the state at index 0 moves to index 1, 1 moves to 2, etc // the state at index 20 is deleted for (int i = stateBuffer.Length – 1; i > 0; i--) { stateBuffer[i] = stateBuffer[i - 1]; } // insert newest state at 0 stateBuffer[0] = state; // increment state count, up to a maximum of 20 stateCount = Mathf.Max(stateBuffer.Length, stateCount + 1); }
void OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info) { if (stream.isWriting) { // serialize position and rotation Vector3 position = transform.position; Quaternion rotation = transform.rotation; Quaternion camRotation = camTransform.localRotation; stream.Serialize(ref position); stream.Serialize(ref rotation); stream.Serialize(ref camRotation); } else { // deserialize position and rotation Vector3 position = Vector3.zero; Quaternion rotation = Quaternion.identity; Quaternion camRotation = Quaternion.identity; stream.Serialize(ref position); stream.Serialize(ref rotation); stream.Serialize(ref camRotation); // store values to be interpolated towards lastReceivedPos = position; lastReceivedRot = rotation; lastReceivedCamRot = camRotation; // buffer network state networkState state = new networkState(); state.Position = position; state.Rotation = rotation; state.CamRotation = camRotation; state.Timestamp = info.timestamp; bufferState(state); } }