SHOW:
|
|
- or go back to the newest paste.
1 | using UnityEngine; | |
2 | using System.Collections; | |
3 | ||
4 | //Predictor script for client | |
5 | //with client side prediction | |
6 | ||
7 | public class C_Predictor : MonoBehaviour { | |
8 | ||
9 | public float pingMargin = 0.5f; | |
10 | ||
11 | private float clientPing; | |
12 | ||
13 | private NetState[] serverStateBuffer = new NetState[20]; | |
14 | ||
15 | private NetState[] clientStateBuffer = new NetState[20]; | |
16 | ||
17 | //Keep track of what Slots are used | |
18 | private int m_LocalStateCount; | |
19 | ||
20 | // Stat variabels for prediction stuff | |
21 | private float m_TimeAccuracy = 0; | |
22 | private float m_PredictionAccuracy = 0; | |
23 | private bool m_FixError = false; | |
24 | private Vector3 m_NewPosition; | |
25 | private Quaternion m_NewRotation; | |
26 | ||
27 | // The position vector distance to start error correction. The higher the latency the higher this | |
28 | // value should be or it constantly tries to correct errors in prediction | |
29 | public float m_PredictionThreshold = 0.3F; | |
30 | ||
31 | // Time difference in milliseconds where we check for error in position. If the server time value | |
32 | // of a state is too different from the local state time then the error correction comparison is | |
33 | // highly unreliable and might try to correct more errors than there really are. | |
34 | public float m_TimeThreshold = 0.05F; | |
35 | ||
36 | ||
37 | ||
38 | public void uLink_OnSerializeNetworkView(uLink.BitStream stream, uLink.NetworkMessageInfo info) | |
39 | { | |
40 | if(!stream.isWriting) | |
41 | { | |
42 | Vector3 pos = Vector3.zero; | |
43 | Quaternion rot = Quaternion.identity; | |
44 | ||
45 | stream.Serialize(ref pos, 0.001f); | |
46 | stream.Serialize(ref rot, 0.001f); | |
47 | ||
48 | - | //receiver.serverPos = pos; |
48 | + | |
49 | - | //receiver.serverRot = rot; |
49 | + | |
50 | for(int i = serverStateBuffer.Length - 1; i >= 1; i--) | |
51 | - | //smoothly correct client pos |
51 | + | |
52 | - | //receiver.lerpToTarget(); //Bug lerp immediately the player to the final pos and with the interpolation the player return back |
52 | + | |
53 | } | |
54 | ||
55 | //Override the first element with the latest server info | |
56 | serverStateBuffer[0] = new NetState((float)info.timestamp, pos, rot); | |
57 | ||
58 | /*int m_TimestampCount; | |
59 | for(int i = 0; i < m_TimestampCount-1; i++) | |
60 | { | |
61 | if(serverStateBuffer[i].timeStamp < serverStateBuffer[i + 1].timeStamp) | |
62 | { | |
63 | Debug.Log("State inconsistent"); | |
64 | } | |
65 | }*/ | |
66 | ||
67 | } | |
68 | ||
69 | } | |
70 | ||
71 | // Use this for initialization | |
72 | void Start () | |
73 | { | |
74 | StartCoroutine(StoreLocalMovement()); | |
75 | } | |
76 | ||
77 | IEnumerator StoreLocalMovement() | |
78 | { | |
79 | while(true) | |
80 | { | |
81 | yield return new WaitForSeconds(1/10); | |
82 | ||
83 | //shift buffer content | |
84 | for(int i = clientStateBuffer.Length - 1; i >= 1; i--) | |
85 | { | |
86 | clientStateBuffer[i] = clientStateBuffer[i - 1]; | |
87 | } | |
88 | ||
89 | clientStateBuffer[0] = new NetState((float)uLink.Network.time, transform.position, transform.rotation); | |
90 | ||
91 | m_LocalStateCount = Mathf.Min(m_LocalStateCount + 1, clientStateBuffer.Length); | |
92 | ||
93 | // | |
94 | //Check if the client side prediction has an error | |
95 | // | |
96 | ||
97 | //Find the local buffered state which is closest to network state in time | |
98 | int j = 0; | |
99 | bool match = false; | |
100 | for(j = 0; j < m_LocalStateCount - 1; j++) | |
101 | { | |
102 | if(serverStateBuffer[0] != null) | |
103 | { | |
104 | if(serverStateBuffer[0].timeStamp <= clientStateBuffer[j].timeStamp && clientStateBuffer[j].timeStamp - serverStateBuffer[0].timeStamp <= m_TimeThreshold) | |
105 | { | |
106 | if(Debug.isDebugBuild) | |
107 | { | |
108 | Debug.Log("Comparing state " + j + "localtime: " + clientStateBuffer[j].timeStamp + " networktime: " + serverStateBuffer[0].timeStamp); | |
109 | Debug.Log("Local: " + clientStateBuffer[j].pos + " Network: " + serverStateBuffer[0].pos); | |
110 | } | |
111 | ||
112 | //m_TimeAccuracy = Mathf.Abs(clientStateBuffer[j].timeStamp - serverStateBuffer[0].timeStamp); | |
113 | m_PredictionAccuracy = (Vector3.Distance(clientStateBuffer[j].pos, serverStateBuffer[0].pos)); | |
114 | - | //Debug.Log("Comparing state " + j + "localtime: " + clientStateBuffer[j].timeStamp + " networktime: " + serverStateBuffer[0].timeStamp); |
114 | + | |
115 | - | //Debug.Log("Local: " + clientStateBuffer[j].pos + " Network: " + serverStateBuffer[0].pos); |
115 | + | |
116 | } | |
117 | } | |
118 | } | |
119 | ||
120 | if(!match) | |
121 | { | |
122 | //Debug.log("Not match"); | |
123 | } | |
124 | else if(m_PredictionAccuracy > m_PredictionThreshold) //if prediction is off, diverge current location by the amount of the offset | |
125 | { | |
126 | if(Debug.isDebugBuild) Debug.Log("PredictionAccuracy sup to Predictionthreshold"); | |
127 | ||
128 | //Find how fat we travelled since the prediction failed | |
129 | Vector3 localMovement = clientStateBuffer[j].pos - clientStateBuffer[0].pos; | |
130 | ||
131 | //"Erase" old value in the local buffer | |
132 | m_LocalStateCount = 1; | |
133 | ||
134 | //New position which we need to converge to in the update loop | |
135 | m_NewPosition = serverStateBuffer[0].pos; | |
136 | ||
137 | m_NewRotation = serverStateBuffer[0].rot; | |
138 | ||
139 | //Trigger the new position convergence routine | |
140 | m_FixError = true; | |
141 | } | |
142 | else | |
143 | { | |
144 | m_FixError = false; | |
145 | } | |
146 | } | |
147 | } | |
148 | ||
149 | // Update is called once per frame | |
150 | void Update () | |
151 | { | |
152 | if(m_FixError) | |
153 | { | |
154 | //transform.position = Vector3.Lerp(m_NewPosition, transform.position, difference.magnitude); | |
155 | Vector3 predictPos = (m_NewPosition/2) + (clientStateBuffer[0].pos/2); | |
156 | Vector3 difference = predictPos - transform.position; | |
157 | ||
158 | ||
159 | transform.position = Vector3.Lerp(transform.position, predictPos, difference.magnitude); | |
160 | transform.rotation = Quaternion.Slerp(transform.rotation, m_NewRotation, difference.magnitude); | |
161 | } | |
162 | ||
163 | ||
164 | } | |
165 | ||
166 | } |