Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using UnityEngine;
- using System.Collections;
- //Predictor script for client
- //with client side prediction
- public class C_Predictor : MonoBehaviour {
- public float pingMargin = 0.5f;
- private float clientPing;
- private NetState[] serverStateBuffer = new NetState[20];
- private NetState[] clientStateBuffer = new NetState[20];
- //Keep track of what Slots are used
- private int m_LocalStateCount;
- // Stat variabels for prediction stuff
- private float m_TimeAccuracy = 0;
- private float m_PredictionAccuracy = 0;
- private bool m_FixError = false;
- private Vector3 m_NewPosition;
- private Quaternion m_NewRotation;
- // The position vector distance to start error correction. The higher the latency the higher this
- // value should be or it constantly tries to correct errors in prediction
- public float m_PredictionThreshold = 0.3F;
- // Time difference in milliseconds where we check for error in position. If the server time value
- // of a state is too different from the local state time then the error correction comparison is
- // highly unreliable and might try to correct more errors than there really are.
- public float m_TimeThreshold = 0.05F;
- public void uLink_OnSerializeNetworkView(uLink.BitStream stream, uLink.NetworkMessageInfo info)
- {
- if(!stream.isWriting)
- {
- Vector3 pos = Vector3.zero;
- Quaternion rot = Quaternion.identity;
- stream.Serialize(ref pos, 0.001f);
- stream.Serialize(ref rot, 0.001f);
- //take care of data for interpolating remote objects movements
- //Shift up the buffer
- for(int i = serverStateBuffer.Length - 1; i >= 1; i--)
- {
- serverStateBuffer[i] = serverStateBuffer[i - 1];
- }
- //Override the first element with the latest server info
- serverStateBuffer[0] = new NetState((float)info.timestamp, pos, rot);
- /*int m_TimestampCount;
- for(int i = 0; i < m_TimestampCount-1; i++)
- {
- if(serverStateBuffer[i].timeStamp < serverStateBuffer[i + 1].timeStamp)
- {
- Debug.Log("State inconsistent");
- }
- }*/
- }
- }
- // Use this for initialization
- void Start ()
- {
- StartCoroutine(StoreLocalMovement());
- }
- IEnumerator StoreLocalMovement()
- {
- while(true)
- {
- yield return new WaitForSeconds(1/10);
- //shift buffer content
- for(int i = clientStateBuffer.Length - 1; i >= 1; i--)
- {
- clientStateBuffer[i] = clientStateBuffer[i - 1];
- }
- clientStateBuffer[0] = new NetState((float)uLink.Network.time, transform.position, transform.rotation);
- m_LocalStateCount = Mathf.Min(m_LocalStateCount + 1, clientStateBuffer.Length);
- //
- //Check if the client side prediction has an error
- //
- //Find the local buffered state which is closest to network state in time
- int j = 0;
- bool match = false;
- for(j = 0; j < m_LocalStateCount - 1; j++)
- {
- if(serverStateBuffer[0] != null)
- {
- if(serverStateBuffer[0].timeStamp <= clientStateBuffer[j].timeStamp && clientStateBuffer[j].timeStamp - serverStateBuffer[0].timeStamp <= m_TimeThreshold)
- {
- if(Debug.isDebugBuild)
- {
- Debug.Log("Comparing state " + j + "localtime: " + clientStateBuffer[j].timeStamp + " networktime: " + serverStateBuffer[0].timeStamp);
- Debug.Log("Local: " + clientStateBuffer[j].pos + " Network: " + serverStateBuffer[0].pos);
- }
- //m_TimeAccuracy = Mathf.Abs(clientStateBuffer[j].timeStamp - serverStateBuffer[0].timeStamp);
- m_PredictionAccuracy = (Vector3.Distance(clientStateBuffer[j].pos, serverStateBuffer[0].pos));
- match = true;
- break;
- }
- }
- }
- if(!match)
- {
- //Debug.log("Not match");
- }
- else if(m_PredictionAccuracy > m_PredictionThreshold) //if prediction is off, diverge current location by the amount of the offset
- {
- if(Debug.isDebugBuild) Debug.Log("PredictionAccuracy sup to Predictionthreshold");
- //Find how fat we travelled since the prediction failed
- Vector3 localMovement = clientStateBuffer[j].pos - clientStateBuffer[0].pos;
- //"Erase" old value in the local buffer
- m_LocalStateCount = 1;
- //New position which we need to converge to in the update loop
- m_NewPosition = serverStateBuffer[0].pos;
- m_NewRotation = serverStateBuffer[0].rot;
- //Trigger the new position convergence routine
- m_FixError = true;
- }
- else
- {
- m_FixError = false;
- }
- }
- }
- // Update is called once per frame
- void Update ()
- {
- if(m_FixError)
- {
- //transform.position = Vector3.Lerp(m_NewPosition, transform.position, difference.magnitude);
- Vector3 predictPos = (m_NewPosition/2) + (clientStateBuffer[0].pos/2);
- Vector3 difference = predictPos - transform.position;
- transform.position = Vector3.Lerp(transform.position, predictPos, difference.magnitude);
- transform.rotation = Quaternion.Slerp(transform.rotation, m_NewRotation, difference.magnitude);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement