Li Song, on 26 November 2014 - 01:39 AM, said:
Hi again Karl!
I followed your link to the explanation of HSR which you gave earlier. And noticed this (emphasis mine):
Immediately my algorithm sense went off the charts. Something didn't sit right with not rewinding the shooter so I sat down and drew this up:
As far as my understanding goes, the server sends (some subset of) the authorative world state to the client periodically (say 30Hz). The client performs a prediction (extrapolation) from the last packet to give a smooth visual experience. And smoothly melds the positions when the next world state is received to avoid "popping" where the mechs snap to the correct position. HSR keeps a history of positions for each rewindable entity.
Consider the above diagram, two players run on a parallel course, their positions being perpendicular to each other and the course. Player A aims and shoots at Player B just before she is to run in behind cover. First of all, if only the target position is rewound, then in this case Player A's shot would miss, because the players would no longer be perpendicular for the sake of the hit registration. Second, if both players are rewound only by 1 ping, then the shot would hit the obstacle as the time it took for the servers true state to be transmitted to the client wasn't accounted for. This would support the observation that slow mechs can hit fast lights even with high ping but light dogfights suffer hit-reg issues as both the shooter and the shootee is moving fast. Especially supports the feeling I've had that PPC shots from a spider some times go through the target even though it was a clean hit on my screen.
So, to me it seems like the correct thing to do is to rewind all objects, including the player by one round trip time (RTT), i.e. 2*ping. This is because the player is reacting to content that is delayed by 1 ping and it takes 1 ping for the reaction to reach the server.
Nice diagram!
Were the system to function as you described, then yes there would be a problem. There is a critical point that allows all of this to function in a sensible manner. The way multiplayer algorithms work, in almost every twitch based FPS, is by allowing time to desync between the various agents.
(please excuse my programmer art)
Lets say we start on the server with the following state at T0:
The server is going to transmit P2's position to P1, and P1's position to P2. It takes ~ half of P1's ping for P1 to receive P2's position. Similarly it takes ~ half of P2's ping to receive P1's position. Assuming P1 has slightly lower ping than P2, here are some hypothetical client states after receiving their relevant world updates:
To keep things simple, lets consider P2 shooting directly at P1 given the above frame. P1 is occluded, so we expect the server to fire a trace at P1's position and hit the displayed obstacle.
So P2 sends to the server two pieces of info. His move input state for the specific net frame we're simulating, and the fire command, which includes a bunch of weapon activation info. Due to latency, the server isn't going to receive P2's packets for about another P2 ping / 2 seconds, so by the time the server receives P2's packets, this is what the server world state looks like at time T1:
We're going to hit the obstacle in question, but P1 is clearly out of position for this weapon trace, since he's continued sending movement updates to the server this entire time. Had the obstacle not been present, this would have been a clear miss.
However, P2 knows that he was shooting at P1's position from P2 ping seconds ago. In fact, there is an authoritative server timestamp associated with that position; so when P2 took the shot, he actually told the server 'I'm shooting against server time T0'.
So, the server rewinds the world prior to performing the trace:
And now the server view for this fire trace recreates the client state as seen by P2 when he took the shot locally on his machine.
Hopefully that clears up how things work a bit.