Network input handling

Started by
123 comments, last by hplus0603 11 years, 2 months ago
Considering the timing problem here is how I do it:

Every time you get an update from the server you can calculate the server time ST corresponding to the update. The target client time targCT would be
targCT = ST + RTT + c
where c is a constant that accounts for jitter in the RTT (such that input packets arrive in time with high probability) and RTT is the current estimate for the round trip time.
The actual client time CT is updated with the internal clock between each server packet and then adjusted according to something like
CT = 0.99*CT + 0.01*targCT

Note that these calculations are done in (more or less) continuos time.

Considering the client side prediction, I guess if you have an expensive physical simulation, it might be infeasible to calculate the prediction steps. In this case, as mentioned by hplus, you could just render everything at a render time
RT = CT - RTT - IP
and try to mask the control delay somehow.
Advertisement
The main issue is our interaction with the world. The player has the ability to modify the worlds contents via blocks, while it must maintain the player(s) locations and interactions as well. To create a responsive combat system ( which we hope to do ) and manage all of that seems to be a daunting task. Maybe if you knew what we were doing you would better know how to help. Btw, thank you for all of this help... it is simply amazing to have this much guidance and knowledge to assist.

Game goal:
Our main drive is to have players fighting it out over land. This land is the same land that is near 100% dynamic and can be modified. So instead of a player vs a player you have to calculate and manage a player vs a player with block entity interaction as well. Depending on how we render things this could be several thousands functions firing at one time if a player used an explosive that blew up x blocks and all players in the area of the blast. Not saying that whatever was already discussed wont manage that just giving you a bit of scope. We want war and land control to be the central focus.
Here's how I'd approach this:

  • All clients report at a fixed rate, say 20-30Hz
  • Client and server contain the exact same prediction/extrapolation logic
  • As clients report to the server, the server corrects its local simulation (moving forwards only!) to account for the inputs
  • There is no requirement for timing lockstep; the server waits for no one
  • Once the server has received some inputs for a tick, it relays the results of its simulation to the appropriate clients
  • This relay happens at the end of the server tick regardless of who has reported in
  • The server tracks the delay between when it expected inputs to be reported and when it actually sees them
  • This is used to inform extrapolation on both the server and other clients
  • Since everyone does the same extrapolation logic, all clients will appear to be in sync but actually lag behind the server due to relay time


When major state changes are relayed from the server to clients, you compute the last known transmission delay (based on the tracked latency) and tell clients to fast-forward their simulation to match. The result is that you might "miss" the first few rendered frames of the world state changing, but the result will be accurate and mostly correctly timed.

The solution to this is to delay local actions by the transmission delay factor, and hide the delay using animations. For example, suppose you have a rocket launcher that can radically alter terrain/buildings/etc. When player A fires a rocket, he sees an instant animation/sound effect/etc. of the launcher charging up to fire. At the same instant, you tell the server to fire the rocket. When the server responds that it has done so, you actually do the rocket/explosion calculations on the client.

This keeps everyone in sync, keeps the game feeling fast, and accurately hides the latency issues involved in distributed simulation.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]


Here's how I'd approach this:

  • All clients report at a fixed rate, say 20-30Hz
  • Client and server contain the exact same prediction/extrapolation logic
  • As clients report to the server, the server corrects its local simulation (moving forwards only!) to account for the inputs
  • There is no requirement for timing lockstep; the server waits for no one
  • Once the server has received some inputs for a tick, it relays the results of its simulation to the appropriate clients
  • This relay happens at the end of the server tick regardless of who has reported in
  • The server tracks the delay between when it expected inputs to be reported and when it actually sees them
  • This is used to inform extrapolation on both the server and other clients
  • Since everyone does the same extrapolation logic, all clients will appear to be in sync but actually lag behind the server due to relay time

When major state changes are relayed from the server to clients, you compute the last known transmission delay (based on the tracked latency) and tell clients to fast-forward their simulation to match. The result is that you might "miss" the first few rendered frames of the world state changing, but the result will be accurate and mostly correctly timed.

The solution to this is to delay local actions by the transmission delay factor, and hide the delay using animations. For example, suppose you have a rocket launcher that can radically alter terrain/buildings/etc. When player A fires a rocket, he sees an instant animation/sound effect/etc. of the launcher charging up to fire. At the same instant, you tell the server to fire the rocket. When the server responds that it has done so, you actually do the rocket/explosion calculations on the client.

This keeps everyone in sync, keeps the game feeling fast, and accurately hides the latency issues involved in distributed simulation.


Not bad, I suppose the only fear now is what people will come up with for hacks. I suppose that is a problem to address when the system is in place and being tested! :P
If you have the server validate everything a client asks to do, it's pretty foolproof.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Not that i am going to do this, but say I wanted to hire somebody to just look over our stuff, do you have any estimates that i should expect to pay to have somebody look at it? like a consultant? I mean we may just figure it all out from just talking like this but I like to have backup plans just in case.
Consulting for this scale of a project would be expensive. Look for something on the order of $150-$200 an hour and a several-week process.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

*nods* indeed, thanks for the heads up!
As clients report to the server, the server corrects its local simulation (moving forwards only!) to account for the inputs[/quote]

Corrects it how? Can you explain in more detail what happens here?

This is used to inform extrapolation on both the server and other clients[/quote]

Can you expand on this point too? I don't understand what you mean by "inform extrapolation".

The solution to this is to delay local actions by the transmission delay factor, and hide the delay using animations.[/quote]

We can do that for some things, but some might need to be instant actions. What do you do about that then? Even world of warcraft has some instant-cast spells, so how do they handle that?

Considering the timing problem here is how I do it:

Every time you get an update from the server you can calculate the server time ST corresponding to the update. The target client time targCT would be
targCT = ST + RTT + c
where c is a constant that accounts for jitter in the RTT (such that input packets arrive in time with high probability) and RTT is the current estimate for the round trip time.
The actual client time CT is updated with the internal clock between each server packet and then adjusted according to something like
CT = 0.99*CT + 0.01*targCT

Note that these calculations are done in (more or less) continuos time.

Considering the client side prediction, I guess if you have an expensive physical simulation, it might be infeasible to calculate the prediction steps. In this case, as mentioned by hplus, you could just render everything at a render time
RT = CT - RTT - IP
and try to mask the control delay somehow.


I keep trying to figure out how this would play out and I can't see how it could work:

Client A has RTT of 200ms
Client B has RTT of 200ms
Interpolation time of 50ms

Server Tick: 200, Client render: 150, Client Tick 400: Client B moves forward
Server Tick: 300, Client render: 250, Client Tick 500: Client B moves forward again. Server receives move command for tick 400
Server Tick: 400, Client render: 350, Client Tick 600: Server applies move and sends out world state. Server receives second move command for tick 500
Server Tick: 450, Client render: 400, Client Tick 650: At this point client A should see client B move, but the world state still has another 50ms before it reaches client A
Server Tick: 500, Client render: 450, Client Tick 700: Client A receives world state for tick 400. Now what?


Valve defaults to an interpolation time of 100ms. In this situation if the interp time was set to that, the client would have just barely received it in time. If the packet took a little longer than 100ms, it would have still been too late.

This topic is closed to new replies.

Advertisement