1- using MLAPI . MonoBehaviours . Core ;
1+ using System . Collections . Generic ;
2+ using MLAPI . MonoBehaviours . Core ;
23using MLAPI . NetworkingManagerComponents . Binary ;
34using System . IO ;
45using UnityEngine ;
@@ -11,11 +12,16 @@ namespace MLAPI.MonoBehaviours.Prototyping
1112 [ AddComponentMenu ( "MLAPI/NetworkedTransform" ) ]
1213 public class NetworkedTransform : NetworkedBehaviour
1314 {
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 ;
1925 /// <summary>
2026 /// Is the sends per second assumed to be the same across all instances
2127 /// </summary>
@@ -43,7 +49,6 @@ public class NetworkedTransform : NetworkedBehaviour
4349 /// The min degrees to rotate before a send it sent
4450 /// </summary>
4551 public float MinDegrees = 1.5f ;
46- private float timeForLerp ;
4752 private float lerpT ;
4853 private Vector3 lerpStartPos ;
4954 private Quaternion lerpStartRot ;
@@ -53,18 +58,17 @@ public class NetworkedTransform : NetworkedBehaviour
5358 private float lastSendTime ;
5459 private Vector3 lastSentPos ;
5560 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 > ( ) ;
6565
6666 private static byte [ ] positionUpdateBuffer = new byte [ 24 ] ;
6767
68+ public delegate bool MoveValidationDelegate ( Vector3 oldPos , Vector3 newPos ) ;
69+
70+ public MoveValidationDelegate IsMoveValidDelegate = null ;
71+
6872 private void OnValidate ( )
6973 {
7074 if ( ! AssumeSyncedSends && InterpolatePosition )
@@ -77,6 +81,11 @@ private void OnValidate()
7781 MinMeters = 0 ;
7882 }
7983
84+ private float GetTimeForLerp ( Vector3 pos1 , Vector3 pos2 )
85+ {
86+ return 1f / DistanceSendrate . Evaluate ( Vector3 . Distance ( pos1 , pos2 ) ) ;
87+ }
88+
8089 /// <summary>
8190 /// Registers message handlers
8291 /// </summary>
@@ -90,10 +99,6 @@ public override void NetworkStart()
9099 {
91100 RegisterMessageHandler ( "MLAPI_OnRecieveTransformFromServer" , OnRecieveTransformFromServer ) ;
92101 }
93- if ( AssumeSyncedSends )
94- {
95- timeForLerp = 1f / SendsPerSecond ;
96- }
97102
98103 lastSentRot = transform . rotation ;
99104 lastSentPos = transform . position ;
@@ -110,7 +115,7 @@ private void Update()
110115 if ( isOwner || isLocalPlayer || ( OwnerClientId == NetworkingManager . singleton . NetworkConfig . NetworkTransport . InvalidDummyId && isServer ) )
111116 {
112117 //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 ) )
114119 {
115120 lastSendTime = NetworkingManager . singleton . NetworkTime ;
116121 lastSentPos = transform . position ;
@@ -145,15 +150,27 @@ private void Update()
145150 //Snap, set T to 1 (100% of the lerp)
146151 lerpT = 1f ;
147152 }
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+
149162 transform . position = Vector3 . Lerp ( lerpStartPos , lerpEndPos , lerpT ) ;
150163 transform . rotation = Quaternion . Slerp ( lerpStartRot , lerpEndRot , lerpT ) ;
151164 }
152165 }
166+
167+ if ( isServer ) CheckForMissedSends ( ) ;
153168 }
154169
155170 private void OnRecieveTransformFromServer ( uint clientId , BitReader reader )
156171 {
172+ if ( ! enabled ) return ;
173+
157174 byte [ ] data = reader . ReadByteArray ( ) ;
158175 using ( MemoryStream stream = new MemoryStream ( data ) )
159176 {
@@ -178,6 +195,8 @@ private void OnRecieveTransformFromServer(uint clientId, BitReader reader)
178195
179196 private void OnRecieveTransformFromClient ( uint clientId , BitReader reader )
180197 {
198+ if ( ! enabled ) return ;
199+
181200 byte [ ] data = reader . ReadByteArray ( ) ;
182201 using ( MemoryStream readStream = new MemoryStream ( data ) )
183202 {
@@ -190,6 +209,13 @@ private void OnRecieveTransformFromClient(uint clientId, BitReader reader)
190209 float xRot = bReader . ReadSingle ( ) ;
191210 float yRot = bReader . ReadSingle ( ) ;
192211 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+ }
193219
194220 if ( InterpolateServer )
195221 {
@@ -215,14 +241,38 @@ private void OnRecieveTransformFromClient(uint clientId, BitReader reader)
215241 writer . Write ( yRot ) ;
216242 writer . Write ( zRot ) ;
217243 }
218- if ( EnableProximity )
244+ if ( EnableRange )
219245 {
220246 // 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 ++ )
222248 {
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
224273 {
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 ) ;
226276 }
227277 }
228278 }
@@ -234,5 +284,36 @@ private void OnRecieveTransformFromClient(uint clientId, BitReader reader)
234284 }
235285 }
236286 }
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+ }
237318 }
238319}
0 commit comments