Im working on server side validated movement in a 3d environment
But for some reason UDP is very unpredictable. My Unity Client runs at a fixed 50 FPS, so every 0.02 seconds or 20milliseconds it sends an UDP TransformUpdate request.
But on the serverside the UDP request sometimes has a deltaTime since last request of 0 milliseconds or 5 milliseconds 0_0 while the distance between the two transform updates can swing wildly from 0.1meter to 0.4m....
This doesnt make any sense, so I was thinking multiple threads are calling my UpdateTransform on serverside at the same time, resulting in a deltaTime betweenn requests of 0 milliseconds, but this is also not true as I have made all my methods synchronized and it still happens...
Can someone clarify this or provide some resources for me to learn how to validate movement correctly on a UDP connection?
Heres my debug traces:
Code: Select all
11:27:49,264 INFO [SFSWorker:Ext:1] Extensions - {__lib__}: -----------------
11:27:49,264 INFO [SFSWorker:Ext:1] Extensions - {__lib__}: 1. DeltaMillis since last TransformUpdate: 38
11:27:49,276 INFO [SFSWorker:Ext:1] Extensions - {__lib__}: 2. --- TotalDistance: 4.581507205963135 --- TotalTime: 1.0880000591278076 --- ActualSpeed: 4.2109437
11:27:49,277 INFO [SFSWorker:Ext:1] Extensions - {__lib__}: 3. --------------- Speed Evaluation: 0.8421887 ----- QueueSize: 50
11:27:49,278 INFO [SFSWorker:Ext:1] Extensions - {__lib__}: -----------------
11:27:49,278 INFO [SFSWorker:Ext:4] Extensions - {__lib__}: -----------------
11:27:49,278 INFO [SFSWorker:Ext:4] Extensions - {__lib__}: 1. DeltaMillis since last TransformUpdate: 0
11:27:49,279 INFO [SFSWorker:Ext:4] Extensions - {__lib__}: 1. newTransform.Milliseconds: 173989500 lastPos.Milliseconds: 173989500
11:27:49,280 INFO [SFSWorker:Ext:4] Extensions - {__lib__}: 2. --- TotalDistance: 4.59747838973999 --- TotalTime: 1.0369999408721924 --- ActualSpeed: 4.433441
11:27:49,280 INFO [SFSWorker:Ext:4] Extensions - {__lib__}: 3. --------------- Speed Evaluation: 0.88668823 ----- QueueSize: 50
11:27:49,281 INFO [SFSWorker:Ext:4] Extensions - {__lib__}: -----------------
11:27:49,296 INFO [SFSWorker:Ext:3] Extensions - {__lib__}: -----------------
11:27:49,296 INFO [SFSWorker:Ext:3] Extensions - {__lib__}: 1. DeltaMillis since last TransformUpdate: 31
11:27:49,310 INFO [SFSWorker:Ext:3] Extensions - {__lib__}: 2. --- TotalDistance: 4.542852878570557 --- TotalTime: 1.0509999990463257 --- ActualSpeed: 4.32241
11:27:49,311 INFO [SFSWorker:Ext:3] Extensions - {__lib__}: 3. --------------- Speed Evaluation: 0.86448205 ----- QueueSize: 50
11:27:49,312 INFO [SFSWorker:Ext:3] Extensions - {__lib__}: -----------------
11:27:52,358 INFO [SFSWorker:Ext:1] Extensions - {__lib__}: -----------------
11:27:52,360 INFO [SFSWorker:Ext:1] Extensions - {__lib__}: 1. DeltaMillis since last TransformUpdate: 50
11:27:52,374 INFO [SFSWorker:Ext:1] Extensions - {__lib__}: 2. --- TotalDistance: 0.42358484864234924 --- TotalTime: 0.1379999965429306 --- ActualSpeed: 3.0694554
11:27:52,375 INFO [SFSWorker:Ext:1] Extensions - {__lib__}: 3. --------------- Speed Evaluation: 0.61389107 ----- QueueSize: 4
11:27:52,382 INFO [SFSWorker:Ext:1] Extensions - {__lib__}: -----------------
11:27:52,384 INFO [SFSWorker:Ext:3] Extensions - {__lib__}: -----------------
11:27:52,408 INFO [SFSWorker:Ext:3] Extensions - {__lib__}: 1. DeltaMillis since last TransformUpdate: 121
11:27:52,409 INFO [SFSWorker:Ext:3] Extensions - {__lib__}: 2. --- TotalDistance: 0.828595757484436 --- TotalTime: 0.2590000033378601 --- ActualSpeed: 3.1992114
11:27:52,416 INFO [SFSWorker:Ext:3] Extensions - {__lib__}: 3. --------------- Speed Evaluation: 0.6398423 ----- QueueSize: 5
11:27:52,416 INFO [SFSWorker:Ext:3] Extensions - {__lib__}: -----------------
11:27:52,432 INFO [SFSWorker:Ext:2] Extensions - {__lib__}: -----------------
11:27:52,434 INFO [SFSWorker:Ext:2] Extensions - {__lib__}: 1. DeltaMillis since last TransformUpdate: 2
11:27:52,459 INFO [SFSWorker:Ext:2] Extensions - {__lib__}: 1. newTransform.Milliseconds: 173992471 lastPos.Milliseconds: 173992473
11:27:52,461 INFO [SFSWorker:Ext:2] Extensions - {__lib__}: 2. --- TotalDistance: 0.9114917516708374 --- TotalTime: 0.26100000739097595 --- ActualSpeed: 3.4923055
11:27:52,466 INFO [SFSWorker:Ext:2] Extensions - {__lib__}: 3. --------------- Speed Evaluation: 0.6984611 ----- QueueSize: 6
11:27:52,466 INFO [SFSWorker:Ext:2] Extensions - {__lib__}: -----------------
For example:
Code: Select all
11:27:49,278 INFO [SFSWorker:Ext:4] Extensions - {__lib__}: -----------------
11:27:49,278 INFO [SFSWorker:Ext:4] Extensions - {__lib__}: 1. DeltaMillis since last TransformUpdate: 0
11:27:49,279 INFO [SFSWorker:Ext:4] Extensions - {__lib__}: 1. newTransform.Milliseconds: 173989500 lastPos.Milliseconds: 173989500
11:27:49,280 INFO [SFSWorker:Ext:4] Extensions - {__lib__}: 2. --- TotalDistance: 4.59747838973999 --- TotalTime: 1.0369999408721924 --- ActualSpeed: 4.433441
11:27:49,280 INFO [SFSWorker:Ext:4] Extensions - {__lib__}: 3. --------------- Speed Evaluation: 0.88668823 ----- QueueSize: 50
11:27:49,281 INFO [SFSWorker:Ext:4] Extensions - {__lib__}: -----------------
QueueSize = a Queue of positions, so I can keep track of distance and time for that whole queue and calculate an average speed for those positions.
SpeedEvaluation = Average Calculated Speed / Actual Allowed Speed. (ex: average speed: 10 / allowedSpeed = 5 evaluates to 2.0f) (Too High!)
Other variables should be clear by their name.
So the problem is as you can see in the logs, sometimes there is 0 milliseconds between requests, other time 2 or 3 milliseconds, othertimes 50 or 200 milliseconds, the higher values are expected as UDP is unreliable, but extremely low values are weird??
Heres how I calculate deltaMillis:
1. Server receive request, call System.nanoTime / 1_000_000 to get milliseconds.
2. I check Check that against the last timestamp, from previous request for that character ( Math.abs(lastTimestamp - thisTimestamp)
3. Store this timestamp so we can compare it with the next one.
My code:
Code: Select all
synchronized static boolean IsValidPosition(
Transform newTransform,
PositionQueue positionQueue,
float maxSpeed) {
TimedVector3 lastPos = positionQueue.GetLastAdded();
if (lastPos == null) {
positionQueue.Add(new TimedVector3(newTransform.Position, newTransform.Milliseconds));
return true;
}
// When server receives request it creates a new Transform object which stores the current nanoTime as a timestamp.
long deltaMillis = Math.abs(newTransform.Milliseconds - lastPos.Milliseconds);
if (deltaMillis < 6) {
_ext.trace("-----------------");
_ext.trace("1. DeltaMillis since last TransformUpdate: " + deltaMillis);
_ext.trace("1. newTransform.Milliseconds: " + newTransform.Milliseconds + " lastPos.Milliseconds: "
+ lastPos.Milliseconds);
positionQueue.Add(new TimedVector3(newTransform.Position, newTransform.Milliseconds));
return IsValidSpeed(positionQueue, maxSpeed);
}
_ext.trace("-----------------");
_ext.trace("1. DeltaMillis since last TransformUpdate: " + deltaMillis);
if (deltaMillis > _maxDeltaMillis) {
positionQueue.Clear();
positionQueue.Add(new TimedVector3(newTransform.Position, newTransform.Milliseconds));
return true;
}
positionQueue.Add(new TimedVector3(newTransform.Position, newTransform.Milliseconds));
return IsValidSpeed(positionQueue, maxSpeed);
}
How is this possible that 2 UDP packets arrive at the same time even though they get sent in 20ms intervals?
It only happens rarely maybe once every 50 packets, so once every second, but it can also happen multiple times in a row in rare occasions.
So the behaviour fluctuates a lot, and Im sure my client is sending one UDP packet every +-20ms, ofcourse it can be 15ms or 25ms but not 0-5ms?
Heres my Unity code btw:
Code: Select all
void FixedUpdate(){
OnMoveEvent?.Invoke(transform.position, transform.eulerAngles);
}
Thanks!