1
- using MLAPI . MonoBehaviours . Core ;
1
+ using System . Collections . Generic ;
2
+ using MLAPI . MonoBehaviours . Core ;
2
3
using MLAPI . NetworkingManagerComponents . Binary ;
3
4
using System . IO ;
4
5
using UnityEngine ;
@@ -11,11 +12,16 @@ namespace MLAPI.MonoBehaviours.Prototyping
11
12
[ AddComponentMenu ( "MLAPI/NetworkedTransform" ) ]
12
13
public class NetworkedTransform : NetworkedBehaviour
13
14
{
14
- /// <summary>
15
- /// Sends per second
16
- /// </summary>
17
- [ Range ( 0f , 120f ) ]
18
- public float SendsPerSecond = 20 ;
15
+ public class ClientSendInfo
16
+ {
17
+ public uint clientId ;
18
+ public float lastSent ;
19
+ public Vector3 ? lastMissedPosition ;
20
+ public Quaternion ? lastMissedRotation ;
21
+ }
22
+
23
+ [ Range ( 0 , 120 ) ]
24
+ public float FixedSendsPerSecond = 20f ;
19
25
/// <summary>
20
26
/// Is the sends per second assumed to be the same across all instances
21
27
/// </summary>
@@ -43,7 +49,6 @@ public class NetworkedTransform : NetworkedBehaviour
43
49
/// The min degrees to rotate before a send it sent
44
50
/// </summary>
45
51
public float MinDegrees = 1.5f ;
46
- private float timeForLerp ;
47
52
private float lerpT ;
48
53
private Vector3 lerpStartPos ;
49
54
private Quaternion lerpStartRot ;
@@ -53,18 +58,17 @@ public class NetworkedTransform : NetworkedBehaviour
53
58
private float lastSendTime ;
54
59
private Vector3 lastSentPos ;
55
60
private Quaternion lastSentRot ;
56
- /// <summary>
57
- /// Should proximity be enabled
58
- /// </summary>
59
- public bool EnableProximity = false ;
60
- /// <summary>
61
- /// The distance to use for proximity
62
- /// </summary>
63
- [ Tooltip ( "If enable proximity is turned on, on clients within this range will be recieving position updates from the server" ) ]
64
- public float ProximityRange = 50 ;
61
+
62
+ public bool EnableRange ;
63
+ public AnimationCurve DistanceSendrate = AnimationCurve . Constant ( 0 , 500 , 20 ) ;
64
+ private readonly Dictionary < uint , ClientSendInfo > clientSendInfo = new Dictionary < uint , ClientSendInfo > ( ) ;
65
65
66
66
private static byte [ ] positionUpdateBuffer = new byte [ 24 ] ;
67
67
68
+ public delegate bool MoveValidationDelegate ( Vector3 oldPos , Vector3 newPos ) ;
69
+
70
+ public MoveValidationDelegate IsMoveValidDelegate = null ;
71
+
68
72
private void OnValidate ( )
69
73
{
70
74
if ( ! AssumeSyncedSends && InterpolatePosition )
@@ -77,6 +81,11 @@ private void OnValidate()
77
81
MinMeters = 0 ;
78
82
}
79
83
84
+ private float GetTimeForLerp ( Vector3 pos1 , Vector3 pos2 )
85
+ {
86
+ return 1f / DistanceSendrate . Evaluate ( Vector3 . Distance ( pos1 , pos2 ) ) ;
87
+ }
88
+
80
89
/// <summary>
81
90
/// Registers message handlers
82
91
/// </summary>
@@ -90,10 +99,6 @@ public override void NetworkStart()
90
99
{
91
100
RegisterMessageHandler ( "MLAPI_OnRecieveTransformFromServer" , OnRecieveTransformFromServer ) ;
92
101
}
93
- if ( AssumeSyncedSends )
94
- {
95
- timeForLerp = 1f / SendsPerSecond ;
96
- }
97
102
98
103
lastSentRot = transform . rotation ;
99
104
lastSentPos = transform . position ;
@@ -110,7 +115,7 @@ private void Update()
110
115
if ( isOwner || isLocalPlayer || ( OwnerClientId == NetworkingManager . singleton . NetworkConfig . NetworkTransport . InvalidDummyId && isServer ) )
111
116
{
112
117
//We own the object OR we are server and the object is not owned by anyone OR we are the object.
113
- if ( NetworkingManager . singleton . NetworkTime - lastSendTime >= timeForLerp && ( Vector3 . Distance ( transform . position , lastSentPos ) > MinMeters || Quaternion . Angle ( transform . rotation , lastSentRot ) > MinDegrees ) )
118
+ if ( NetworkingManager . singleton . NetworkTime - lastSendTime >= ( 1f / FixedSendsPerSecond ) && ( Vector3 . Distance ( transform . position , lastSentPos ) > MinMeters || Quaternion . Angle ( transform . rotation , lastSentRot ) > MinDegrees ) )
114
119
{
115
120
lastSendTime = NetworkingManager . singleton . NetworkTime ;
116
121
lastSentPos = transform . position ;
@@ -145,15 +150,27 @@ private void Update()
145
150
//Snap, set T to 1 (100% of the lerp)
146
151
lerpT = 1f ;
147
152
}
148
- lerpT += Time . unscaledDeltaTime / timeForLerp ;
153
+
154
+ if ( isServer || ! EnableRange )
155
+ lerpT += Time . unscaledDeltaTime / FixedSendsPerSecond ;
156
+ else
157
+ {
158
+ Vector3 myPos = NetworkingManager . singleton . ConnectedClients [ NetworkingManager . singleton . LocalClientId ] . PlayerObject . transform . position ;
159
+ lerpT += Time . unscaledDeltaTime / GetTimeForLerp ( transform . position , myPos ) ;
160
+ }
161
+
149
162
transform . position = Vector3 . Lerp ( lerpStartPos , lerpEndPos , lerpT ) ;
150
163
transform . rotation = Quaternion . Slerp ( lerpStartRot , lerpEndRot , lerpT ) ;
151
164
}
152
165
}
166
+
167
+ if ( isServer ) CheckForMissedSends ( ) ;
153
168
}
154
169
155
170
private void OnRecieveTransformFromServer ( uint clientId , BitReader reader )
156
171
{
172
+ if ( ! enabled ) return ;
173
+
157
174
byte [ ] data = reader . ReadByteArray ( ) ;
158
175
using ( MemoryStream stream = new MemoryStream ( data ) )
159
176
{
@@ -178,6 +195,8 @@ private void OnRecieveTransformFromServer(uint clientId, BitReader reader)
178
195
179
196
private void OnRecieveTransformFromClient ( uint clientId , BitReader reader )
180
197
{
198
+ if ( ! enabled ) return ;
199
+
181
200
byte [ ] data = reader . ReadByteArray ( ) ;
182
201
using ( MemoryStream readStream = new MemoryStream ( data ) )
183
202
{
@@ -190,6 +209,13 @@ private void OnRecieveTransformFromClient(uint clientId, BitReader reader)
190
209
float xRot = bReader . ReadSingle ( ) ;
191
210
float yRot = bReader . ReadSingle ( ) ;
192
211
float zRot = bReader . ReadSingle ( ) ;
212
+
213
+ if ( IsMoveValidDelegate != null && ! IsMoveValidDelegate ( lerpEndPos , new Vector3 ( xPos , yPos , zPos ) ) )
214
+ {
215
+ //Invalid move!
216
+ //TODO: Add rubber band (just a message telling them to go back)
217
+ return ;
218
+ }
193
219
194
220
if ( InterpolateServer )
195
221
{
@@ -215,14 +241,38 @@ private void OnRecieveTransformFromClient(uint clientId, BitReader reader)
215
241
writer . Write ( yRot ) ;
216
242
writer . Write ( zRot ) ;
217
243
}
218
- if ( EnableProximity )
244
+ if ( EnableRange )
219
245
{
220
246
// For instead of Foreach?! TODO!!!
221
- for ( uint i = 0 ; i < NetworkingManager . singleton . ConnectedClients . Count ; i ++ )
247
+ for ( int i = 0 ; i < NetworkingManager . singleton . ConnectedClientsList . Count ; i ++ )
222
248
{
223
- if ( Vector3 . Distance ( NetworkingManager . singleton . ConnectedClients [ i ] . PlayerObject . transform . position , transform . position ) <= ProximityRange )
249
+ if ( ! clientSendInfo . ContainsKey ( NetworkingManager . singleton . ConnectedClientsList [ i ] . ClientId ) )
250
+ {
251
+ clientSendInfo . Add ( NetworkingManager . singleton . ConnectedClientsList [ i ] . ClientId , new ClientSendInfo ( )
252
+ {
253
+ clientId = NetworkingManager . singleton . ConnectedClientsList [ i ] . ClientId ,
254
+ lastMissedPosition = null ,
255
+ lastMissedRotation = null ,
256
+ lastSent = 0
257
+ } ) ;
258
+ }
259
+
260
+ ClientSendInfo info = clientSendInfo [ NetworkingManager . singleton . ConnectedClientsList [ i ] . ClientId ] ;
261
+ Vector3 receiverPosition = NetworkingManager . singleton . ConnectedClientsList [ i ] . PlayerObject . transform . position ;
262
+ Vector3 senderPosition = NetworkingManager . singleton . ConnectedClients [ OwnerClientId ] . PlayerObject . transform . position ;
263
+
264
+ if ( NetworkingManager . singleton . NetworkTime - info . lastSent >= GetTimeForLerp ( receiverPosition , senderPosition ) )
265
+ {
266
+ info . lastSent = NetworkingManager . singleton . NetworkTime ;
267
+ info . lastMissedPosition = null ;
268
+ info . lastMissedRotation = null ;
269
+
270
+ SendToClientTarget ( NetworkingManager . singleton . ConnectedClientsList [ i ] . ClientId , "MLAPI_OnRecieveTransformFromServer" , "MLAPI_POSITION_UPDATE" , positionUpdateBuffer , true ) ;
271
+ }
272
+ else
224
273
{
225
- SendToClientTarget ( NetworkingManager . singleton . ConnectedClients [ i ] . ClientId , "MLAPI_OnRecieveTransformFromServer" , "MLAPI_POSITION_UPDATE" , positionUpdateBuffer , true ) ;
274
+ info . lastMissedPosition = new Vector3 ( xPos , yPos , zPos ) ;
275
+ info . lastMissedRotation = Quaternion . Euler ( xRot , yRot , zRot ) ;
226
276
}
227
277
}
228
278
}
@@ -234,5 +284,36 @@ private void OnRecieveTransformFromClient(uint clientId, BitReader reader)
234
284
}
235
285
}
236
286
}
287
+
288
+ private void CheckForMissedSends ( )
289
+ {
290
+ for ( int i = 0 ; i < NetworkingManager . singleton . ConnectedClientsList . Count ; i ++ )
291
+ {
292
+ ClientSendInfo info = clientSendInfo [ NetworkingManager . singleton . ConnectedClientsList [ i ] . ClientId ] ;
293
+ Vector3 receiverPosition = NetworkingManager . singleton . ConnectedClientsList [ i ] . PlayerObject . transform . position ;
294
+ Vector3 senderPosition = NetworkingManager . singleton . ConnectedClients [ OwnerClientId ] . PlayerObject . transform . position ;
295
+
296
+ if ( NetworkingManager . singleton . NetworkTime - info . lastSent >= GetTimeForLerp ( receiverPosition , senderPosition ) )
297
+ {
298
+ info . lastSent = NetworkingManager . singleton . NetworkTime ;
299
+ info . lastMissedPosition = null ;
300
+ info . lastMissedRotation = null ;
301
+
302
+ SendToClientTarget ( NetworkingManager . singleton . ConnectedClientsList [ i ] . ClientId , "MLAPI_OnRecieveTransformFromServer" , "MLAPI_POSITION_UPDATE" , positionUpdateBuffer , true ) ;
303
+ }
304
+ }
305
+ }
306
+
307
+ public void Teleport ( Vector3 position , Quaternion rotation )
308
+ {
309
+ if ( InterpolateServer && isServer || isClient )
310
+ {
311
+ lerpStartPos = position ;
312
+ lerpStartRot = rotation ;
313
+ lerpEndPos = position ;
314
+ lerpEndRot = rotation ;
315
+ lerpT = 0 ;
316
+ }
317
+ }
237
318
}
238
319
}
0 commit comments