Technical solution to eliminate desync in single-player sessions

"
ScrotieMcB wrote:
"
RogueMage wrote:
The UDP update stream is not used to resync the client, it's intended to reduce the need for resyncs and minimize the abrupt visual disturbance of rubberbanding.
Sorry, but that's just wrong.

By the time the client's commands reach the server, you are out of time; that is the deadline. You don't have time to send anything back to the client in terms of desync prevention; anything you send back will be resyncing the client, because if the client has it wrong at that point, it's already going to be out of sync.

No, it's not the case that you've run out of time and furthermore, the UDP stream does not contain resync data. The server doesn't wait for client commands before sending UDP position updates, it sends them periodically regardless of what the client does. Also, the server is not attempting to resync the client with the UDP updates, it's merely sending positional data that the client can use as it sees fit.

Resync is a drastic fallback that the server initiates when the client's simulation diverges too far from the server's (or when you manually request an /oos). It literally aborts the client's current simulation and replaces it with the server's. That is often abrupt and visually disturbing.

Using UDP updates to calculate corrected movement vectors is a periodic tracking process that the client generates to progressively converge on the server's player and enemy positions. If the client can track the server closely enough, it can avoid triggering the server's resync fallback.
Last edited by RogueMage#7621 on Nov 23, 2013, 10:17:13 PM
"
Sachiru wrote:
Thus, a possible compromise is this:

GGG sends /oos data relevant to monster position in a specified radius (say, Y units) every X milliseconds.

That's not a compromise, it's a different type of system where you're attempting to avoid massive resyncs by performing a series of mini-resyncs. And it is server-directed rather than client-controlled.

The current simulation system works very well when the client is able to accurately predict player and enemy movements that correspond closely enough to the server's to avoid triggering resyncs.

What the UDP stream would do is give the client timely positional information that would enable the client to more accurately predict player and enemy movements.

The goal is to minimize the need for resyncs.
"
RogueMage wrote:
"
ScrotieMcB wrote:
Spoiler
"
RogueMage wrote:
The UDP update stream is not used to resync the client, it's intended to reduce the need for resyncs and minimize the abrupt visual disturbance of rubberbanding.
Sorry, but that's just wrong.

By the time the client's commands reach the server, you are out of time; that is the deadline. You don't have time to send anything back to the client in terms of desync prevention; anything you send back will be resyncing the client, because if the client has it wrong at that point, it's already going to be out of sync.
No, it's not the case that you've run out of time. The server doesn't wait for client commands before sending UDP position updates, it sends them periodically regardless of what the client does.
You need to understand that the client animates player commands instantly and that anything which the server sends via UDP as a result of said commands will be at least a round-trip-ping late. The fact that the UDP information is being sent continuously doesn't change the fact that it's continuously late relative to player input.

UDP isn't viable for desync prevention. TCP isn't either, because the server doesn't have time for additional communication. Better client prediction is the only way to prevent desync; UDP vs TCP is a resync consideration.
When Stephen Colbert was killed by HYDRA's Project Insight in 2014, the comedy world lost a hero. Since his life model decoy isn't up to the task, please do not mistake my performance as political discussion. I'm just doing what Steve would have wanted.
Last edited by ScrotieMcB#2697 on Nov 23, 2013, 8:58:43 PM
"
ScrotieMcB wrote:
You need to understand that the client animates player commands instantly and that anything which the server sends via UDP as a result of said commands will be at least a round-trip-ping late. The fact that the UDP information is being sent continuously doesn't change the fact that it's continuously late relative to player input.

Of course there is always network latency, but in this case it's not a round-trip, it's just the time it takes the client to receive each UDP update. As you state, the client continues to run its simulation regardless of any positional updates it receives from the server. The UDP stream is always an independent summary of the server's simulation, it's not a direct response to any client action or request.

One aspect I didn't stress earlier is that the UDP stream is continuously timestamped by the server. That enables the client to evaluate the timeliness of each server update. In calculating movement vector corrections, the client is making use of the first derivative of the client and server's positional data rather than imposing absolute coordinate corrections. In doing so, the client can use latency estimates to predict the server's simulation progress and target its own movement vectors to converge with that prediction. With subsequent updates the convergence gets closer as smaller movement vector corrections are required. It's a periodically updated closed-loop system rather than a reset and resync fallback mechanism.

"
ScrotieMcB wrote:
UDP isn't viable for desync prevention.

There's a crucial reason why UDP can potentially be used for resync prevention: Updates can be streamed far more quickly over UDP than with TCP. As a result, the UDP updates can be more timely than TCP response times, giving the client a margin it can use to calculate movement correction vectors that will tend to converge and track more closely with the server's simulation. If the client can track the server closely enough, it can avoid triggering the client's resync fallback mechanism.
Last edited by RogueMage#7621 on Nov 23, 2013, 10:22:46 PM
It's important to emphasize this is for minimizing incremental error. This is not an authoritative data stream.

"
Skogenik wrote:

It's also worth noting that the majority of traffic between these two endpoints consists of packets ~68 bytes in length.


If you can cram even a state delta, let alone all position data, for Coward's Trial into 36 bytes I will be very impressed. If this uses floating-point position you're at a healthy 12 bytes per object or so.

"
At that size, I don't think the overhead of TCP/IP routing


TCP/IP routing is the same as UDP/IP routing, they both use IP to route. Also, since you only care about the latest state on this stream you don't need reliable delivery.

"
Another concern, although I freely admit I've not researched this fully, is that Unfortunately, many people are behind a NAT, whether they know it or not and Getting UDP through NAT requires a specialized technique that is by no means standardized.


Routers generally handle UDP started by the client just fine, otherwise you wouldn't be here since DNS uses UDP.

Do you have anything else you copied from Baby's First Network Programming Textbook or are we good now?
Last edited by genericacc#3481 on Nov 23, 2013, 11:02:36 PM
"
ScrotieMcB wrote:
You need to understand that the client animates player commands instantly and that anything which the server sends via UDP as a result of said commands will be at least a round-trip-ping late. The fact that the UDP information is being sent continuously doesn't change the fact that it's continuously late relative to player input.


Client command replay after corrections has been around and generally known for, oh, 15 years or so. This is a solved problem.

Also, some of you arguing TCP/UDP is hilarious. Games use UDP; otherwise they'd stall for seconds at a time when packets are lost or misordered. The protocol has nothing to do with routers or NAT traversal; in all but pathological cases router issues are about hosting, not clients.
Last edited by Mysterial#1424 on Nov 23, 2013, 11:06:15 PM
@RogueMage:
If you're going to stream it with UDP, why even bother with a TCP fallback mechanism? You're already sending all of that information constantly. UDP would be the resync mechanism, you don't need another.

A resync doesn't have to be formally requested to be a resync. However, it isn't desync prevention because the UDP information is always at least a round-trip-ping time late.

Naturally all movement data sent from server to client should be timestamped. Obviously.

However, the idea that you can use data from the past to make predictions on the future is... well, it doesn't work so well. Let's work out an example using your system.
"
0ms: User commands character to move forward. Character immediately starts moving forward on the client.

75ms: User command reaches server. Character immediately starts moving forward on the server.

160ms: User receives movement information from server. The client sees from the timestamp that the server sent this information at 75ms.

1500ms: Character on client reaches aggro range of enemies. They do nothing because no UDP update from them yet.

1575ms: Character on server reaches aggro range of enemies. They begin moving to intercept the player.

1675ms: UDP update with information regarding monster movement reaches the client. Monsters begin moving the intercept the player. The client sees from the timestamp that the server sent this information at 1575ms.
Now what does the client do at 1675ms? Does it instantly teleport monsters to the predicted position on the server? If so, because this is the "prediction mechanism," you can expect to see small, non-fluid teleports every time you draw aggro on monsters and they start moving towards you. Does it allow them to "catch up" without teleports by giving them additional movespeed? Note that regardless of which you choose here, the monsters start moving late on the client.

You might argue that the server should send something in anticipation, say, at 1425ms, so that it reaches the client around 1500ms. But at this point we're both trusting the client's latency, which could be made artificially high by a malicious client, and can change over time anyway, so old latency isn't necessarily current latency. We'd also be trying to predict that the client won't change their course during a window of time... in this case, any client command to stop which began from about 1325ms and 1500ms would be ignored and treated as triggering aggro on the enemies, even if the character never really came within range.

Although PoE currently uses TCP instead of UDP, a lot of GGG's current problems with client-side prediction of movement are based on exactly these problems — relying on server initiation of monster movement. Failure to properly predict movement is one of the biggest causes of desync. UDP doesn't magically make this problems go away and more than TCP does... it's simply a more efficient protocol for continuously streaming resync data.
When Stephen Colbert was killed by HYDRA's Project Insight in 2014, the comedy world lost a hero. Since his life model decoy isn't up to the task, please do not mistake my performance as political discussion. I'm just doing what Steve would have wanted.
Last edited by ScrotieMcB#2697 on Nov 23, 2013, 11:29:49 PM
"
Mysterial wrote:

Also, some of you arguing TCP/UDP is hilarious. Games use UDP; otherwise they'd stall for seconds at a time when packets are lost or misordered. The protocol has nothing to do with routers or NAT traversal; in all but pathological cases router issues are about hosting, not clients.


Well, let's count the myriad ways in which this post is wrong.

1. There exist games that use TCP and games that exist UDP.
2. You don't stall for "seconds at a time" with UDP any more than you do with TCP because it's possible to implement reliable packet transmission/packet ordering on top of UDP too.
3. You don't always need packet ordering for games because certain events (e.g. skill use) don't depend on ordering much.
4. You don't always need reliable transmission for games. Trivially if you send entire game state you only need the latest one and resending an old state is generally a waste of time.

There's probably a few more but I think that's good.

"
ScrotieMcB wrote:
However, the idea that you can use data from the past to make predictions on the future is...


Exactly what's being done in PoE now?
Last edited by genericacc#3481 on Nov 23, 2013, 11:45:45 PM
"
genericacc wrote:
"
ScrotieMcB wrote:
However, the idea that you can use data from the past to make predictions on the future is...
Exactly what's being done in PoE now?
Doesn't seem to work so great, does it?
When Stephen Colbert was killed by HYDRA's Project Insight in 2014, the comedy world lost a hero. Since his life model decoy isn't up to the task, please do not mistake my performance as political discussion. I'm just doing what Steve would have wanted.
"
ScrotieMcB wrote:
Doesn't seem to work so great, does it?


You can't predict future state reliably given stale data, sure. You can correct your current expectation of present state given a more correct observation of previous state though, and that'll improve your prediction of future state a bit.

Probably not an extremely high effect here but even tiny variances in starting data vary output significantly for PDE-based simulations
Last edited by genericacc#3481 on Nov 23, 2013, 11:50:45 PM

Report Forum Post

Report Account:

Report Type

Additional Info