0
\$\begingroup\$

I'm messing around with a 2D game using UDP. I've read some books and articles on the logic of a dedicated server to clients multiplayer game and I can't wrap my head around one thing:

What I've read:
When Client 1 moves, it sends it's input to the SERVER, the SERVER calculates the position, and then sends the new position back to all connected Clients, including Client 1 where the Client 1 player is drawn in the new position. Wouldn't this create a big amount of latency between the local player of Client 1 and their movements?

How I think it should work:
My question is, why not just move the local player based on the movement, and send the new position to the SERVER every time it moves? That what we you press a movement key, it's instant, instead of having to be calculated by the server and sent back and THEN moved.

NOTE: I'm not worried about anti-cheating verification

\$\endgroup\$
  • \$\begingroup\$ You've heard of client-side prediction to eliminate this latency, yes? \$\endgroup\$ – DMGregory May 7 at 18:56
  • \$\begingroup\$ @DMGregory Yes, I just don't understand why we don't do the movement on the client side and send the new position, instead of making the server calculate the inputs. There's got to be a catch to doing that since every game does it the way I've read, I just don't understand why. \$\endgroup\$ – user2578216 May 7 at 19:02
  • \$\begingroup\$ We do do the movement on the client side. AND we send the input for the server to independently do so in a trusted fashion. There's no reason you can't have your cake and eat it too. \$\endgroup\$ – DMGregory May 7 at 19:06
  • \$\begingroup\$ So we move the client locally, send the input (and velocity etc) to server, and it moves it as well? I'm guessing if they're off by a large amount after interpolation you correct it? Right now I have multiple clients sending their positions to the server. The server sends the positions of each player to the other clients and they update accordingly. It's just a constant stream of PositionX and PositionY and enum PlayerAction \$\endgroup\$ – user2578216 May 7 at 20:51
1
\$\begingroup\$

What I've read:

When Client 1 moves, it sends its input to the SERVER, the SERVER calculates the position, and then sends the new position back to all connected Clients, including Client 1 where the Client 1 player is drawn in the new position. Wouldn't this create a big amount of latency between the local player of Client 1 and their movements?

Almost. After Client 1 sends its input to the server, Client 1 also calculates its position, and continues advancing the local game state according to the best knowledge it has. This means you generally see no latency at all here - your immediate outcome is the same as if you were playing an offline game. This is called "client-side prediction".

Most of the time (if you're not using a hacked client, and there are no bugs in the game simulation that cause it to run significantly differently on your device versus the server), the server will agree with your simulation output. So when you get your validated position back from the server, it just confirms the simulation you've already been running and displaying in the meantime, and nothing surprising needs to happen.

But sometimes the server knows something you didn't when you sent that input. In actual fact, another player changed course and collided with you a fraction of a second ago, or put an obstacle in your way, or shot you, etc. but you're finding out about it late because of the communication delay.

In those cases, you'll need to adjust your simulation based on this new information about what happened in the very recent past, re-playing your inputs with this new knowledge of the game state to arrive at a new outcome that's consistent with the "consensus reality" the server has authoritatively determined and broadcast to all players. You can then gradually interpolate the displayed state to this corrected state over a few frames to make the adjustment less jarring.

This same adjustment can help cover smaller divergence in your simulation outcomes due to (hopefully minor) non-determinism in your simulation - like variations in floating point rounding or physics resolutions.

How I think it should work:

My question is, why not just move the local player based on the movement, and send the new position to the SERVER every time it moves?

The biggest problem with this is if the server just trusts any old position it's sent, then it becomes easy for players to hack the game to move faster or teleport or clip through walls etc. Even if you try to add server-side validation, it's generally more work to verify that a given position is a valid outcome of the game rules than it is to just run those game rules on the input directly.

But since you say you don't care about cheating, you can ignore that reason (at your own peril, some would say, but hey, it's your choice to make 😉).

The other reason is that when a conflict arises, simulating from input helps us find the correct resolution to that conflict. If all the server has is a list of positions - some of them based on false assumptions about past game state as we saw above - then it has to work backwards to figure out how those game entities got into those positions, to then figure out where it needs to move them to instead. This again is more work than just playing the game state forward with the history of player inputs, and simulating forward helps you get a more consistent, predictable, fair outcome too. So that's why we often prefer this route, even when stopping cheaters is not a top priority.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ thank you for the detailed explanation! I do appreciate it. \$\endgroup\$ – user2578216 May 7 at 23:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.