Physics Server / Lag Compensation / Out of sync..

Started by
17 comments, last by hplus0603 7 years, 1 month ago

..and no P2P movement it is. :lol:

100 concurrent players online would be amazing. I'm going to use your conservative points about only sending the data when players are in range, if the player is even moving, etc. So looks like the 15 msgs in/out + host server + interpolated movement is ideal for me.

Not as reactive as I'd like at 15.. I might up it a bit.. I'll do more testing and might create a new thread later if I got a whole new issue :P

Advertisement

Hey guys. Not meant to hijack this thread. I am interested at the state synchronization being used in Godot engine but I don't understand the code written in Godot. To be honest I don't even know what language it uses. I just want to know how it achieves the state synchronization and I can't find a clear explanation on their gitHub page: https://github.com/empyreanx/godot-state-sync-demo.

The few questions in my heads are:

1. After I sync the time between server and client, when should I get the first state from the server?

2. Since I am doing state synchronization interpolation, I need to have at least two states to interpolate. After the player logs in, when should the player start the interpolation on client side?

I have already known the concept of state synchronization but when I roll up my sleeves to work I find I can't get through these questions before moving on.

Godot apparently uses GDScript, a language only used by the Godot engine: http://docs.godotengine.org/en/stable/reference/gdscript.html

The "state synchronization" demo seems half-baked to me. Specifically, the README seems to indicate that the client and server both run the simulation, and the server sends full snapshots "at a high rate," and presumably the client applies those snapshots when received.

Exactly how it manages the latency of the applied snapshot isn't clear. It says "Linearly interpolated error correction for position and rotation" which I take to mean that it calculates the delta between server snapshot and local state, divides it into some number of frames, and adds that delta to the physics state of the locally simulated object. It says nothing about time delay or rewriting history, so it may not even be able to do this for player characters, or it may introduce a round-trip delay for player entities.

Also, it lists some rather important bits as missing:

  • Jitter buffer
  • Snap state when distance is greater than some threshold

so, I'd assume that this is not the best tutorial on how to do physics state reconciliation between client and server.

enum Bool { True, False, FileNotFound };

Godot apparently uses GDScript, a language only used by the Godot engine: http://docs.godotengine.org/en/stable/reference/gdscript.html

The "state synchronization" demo seems half-baked to me. Specifically, the README seems to indicate that the client and server both run the simulation, and the server sends full snapshots "at a high rate," and presumably the client applies those snapshots when received.

Exactly how it manages the latency of the applied snapshot isn't clear. It says "Linearly interpolated error correction for position and rotation" which I take to mean that it calculates the delta between server snapshot and local state, divides it into some number of frames, and adds that delta to the physics state of the locally simulated object. It says nothing about time delay or rewriting history, so it may not even be able to do this for player characters, or it may introduce a round-trip delay for player entities.

Also, it lists some rather important bits as missing:

  • Jitter buffer
  • Snap state when distance is greater than some threshold

so, I'd assume that this is not the best tutorial on how to do physics state reconciliation between client and server.

Thank you for pointing that out. Which articles do you recommend if I were to learn to do a proper state synchronization? I know it seems obvious to more experienced developers like you, but I find the information I gathered from the web is fragmented. I just can't put them together to make it work. So far I can do the following:

1. syncing the time between clients and the server.

2. Getting latest states from a data structure.

3. lerping between states.

I have also read a bit about lag compensation. But I am stuck in getting start to receive the first state at the correct time and deciding which state to pick due to various latency.

Which articles do you recommend if I were to learn to do a proper state synchronization?

State synchronization is actually a very delicate subject where the specifics of the implementation has significant impact on the specific "feel" of your game. There's many different building blocks, and they go together in a number of ways, depending on your goals.

Good example links used to be listed in the FAQ (top pinned post) of this forum, although some of them have link-rotted.

Good articles I can think of off-hand include:

- http://www.gamasutra.com/view/feature/131503/1500_archers_on_a_288_network_.php

- http://www.gamasutra.com/view/news/177508/The_lagfighting_techniques_behind_GGPOs_netcode.php

- http://gafferongames.com/2004/12/28/zen-of-networked-physics/

- https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking

Even something as simple as "syncing the time between clients and the server" varies based on what your network model is.

enum Bool { True, False, FileNotFound };

Which articles do you recommend if I were to learn to do a proper state synchronization?

State synchronization is actually a very delicate subject where the specifics of the implementation has significant impact on the specific "feel" of your game. There's many different building blocks, and they go together in a number of ways, depending on your goals.

Good example links used to be listed in the FAQ (top pinned post) of this forum, although some of them have link-rotted.

Good articles I can think of off-hand include:

- http://www.gamasutra.com/view/feature/131503/1500_archers_on_a_288_network_.php

- http://www.gamasutra.com/view/news/177508/The_lagfighting_techniques_behind_GGPOs_netcode.php

- http://gafferongames.com/2004/12/28/zen-of-networked-physics/

- https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking

Even something as simple as "syncing the time between clients and the server" varies based on what your network model is.

Thanks for sharing the references. I have actually read some of them. You are so right about the variation of the "time syncing" part. Yesterday I implemented my first ever state interpolation and if client time and the server time has a time difference less than 10ms the player interpolates very smoothly. However if the time difference is bigger, such as 40ms or 90ms the player will suddenly stop and then after a while just flick to the target position like there is no interpolation at all.

My game demo is very simple. It only shows players moving around on the map. My current interpolation function is like this (written in Javascript):


interpolateState(previousState, currentState, renderTime) {
  if (renderTime <= currentState.timestamp && renderTime >= previousState.timestamp) {
      const total = currentState.timestamp - previousState.timestamp;
      const portion = renderTime - previousState.timestamp;
      const ratio = portion / total;
      player.x = lerp(previousState.x, currentState.x, ratio);
      player.y = lerp(previousState.y, currentState.y, ratio); 
  }
} 

Here server updates every 50ms and the renderTime is the 200ms before the server time which I get from syncing the time with the server at client side. I also put the states I received from the server into a queue which has 3 elements so that on every network update the new state will be pushed into the queue and an existing state will be popped out for use. The queue will only pop a state when it's full, and to interpolate I need to have two states, that's why I choose 200ms before the present time. This simple and naive approach seems to work but I think there are a lot to improve to make my game playable. Is there anything I can work on to fix the lags due to server and client time difference?

There's not enough information to go on with what you posted, but here are a few comments:

  • If you're abruptly replacing previousState and currentState when a new value comes in, then obviously the next time you interpolate, the positions will jump.
  • Your interpolation function does nothing if the render time falls outside your 2 timestamps, so that will stop updating the x and y values, causing things to stop. (And then jump to a new position whenever the render time falls within the value range again.)
  • You should keep all states until they're not needed, rather than just 2. Interpolate between the state slightly older than the render time and the state slightly more recent than the render time. Drop states older than the one before the render time, because you'll no longer need them.
  • Hopefully you are updating renderTime smoothly based on the current client, and not having the server change it.

You might consider starting a new thread for your specific problems.

There's not enough information to go on with what you posted, but here are a few comments:

  • If you're abruptly replacing previousState and currentState when a new value comes in, then obviously the next time you interpolate, the positions will jump.
  • Your interpolation function does nothing if the render time falls outside your 2 timestamps, so that will stop updating the x and y values, causing things to stop. (And then jump to a new position whenever the render time falls within the value range again.)
  • You should keep all states until they're not needed, rather than just 2. Interpolate between the state slightly older than the render time and the state slightly more recent than the render time. Drop states older than the one before the render time, because you'll no longer need them.
  • Hopefully you are updating renderTime smoothly based on the current client, and not having the server change it.

You might consider starting a new thread for your specific problems.

Thanks for your valuable reply. I simply update the client value with the current server value when rendertime is not between the two timestamps. Sorry I haven't posted all my code because the whole thing will make it harder to read. As per your suggestion I rephrase my question and put it in a new thread: https://www.gamedev.net/topic/687361-slow-response-in-state-interpolation-when-time-gap-is-big-between-client-and-server/

And what do you mean by

  • Hopefully you are updating renderTime smoothly based on the current client, and not having the server change it.

?

I get the server time and then rollback 200ms as the render time. I am using a third party module call timesync (https://github.com/enmasseio/timesync) to sync the time between server and client and it seems to be doing the trick. If you don't mind you can reply in the other thread I posted so I will stop here.

What if you don't get a new server time when you need to render the next image?

Typically, you should keep an offset between "local clock time" and "server clock time."

Then, when time comes to render, you read the local clock time, and add the offset, and render the game at that point in time. This will often imply doing interpolation or extrapolation.

Note that "time" may be measured in ticks or seconds, and "render" may also include intermediate simulation step updates. It may even be that your network rate runs at one interval (say, 50 milliseconds,) your simulation runs at another interval (say, 8 milliseconds,) and your render runs at a third interval (say, 16.7 milliseconds,) and you have to use interpolation to go from network to simulation, and then again to go from simulation to render.

enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement