2
\$\begingroup\$

I'm creating a small online multiplayer game where I have multiple thin clients and an authoritative server. Both the client and the server have a fixed game loop.

Now I have a game entity with the following properties:

  • X position: float
  • Y position: float
  • Direction: float

In the client, the entity is in constant velocity changing its direction based on user input and sends an input event to the server.

  • [LEFT, PRESSED]: Entity moves to the left
  • [LEFT, RELEASED]: Entity moves to the right

Every event is queued on the server, and simulated the same way as on the client (calculating the new properties based on trigonometric functions) and the event is send to other players in the room. The other players apply the same simulation to that particular entity (keeping track of what key is pressed for each entity).

Now after some time playing, the position and direction start to drift and stop being in sync. I suspect this has to do with floating-point arithmetic(?)

  1. Is this implementation correct, rather than sending its position and direction every step?

  2. How would I solve this problem? I think I need to make the server the single source of truth and send regular state snapshots to the the clients to correct possible mistakes/drifting? What would be a good interval to keep the clients up to date?

  3. At the moment, I'm broadcasting an event to every player in the room. What would be a nice approach to only send events to players near the entity? Would a quadtree work here (the same I'm using for my collision detection)?

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Your problem is probably not floating point arithmetic but modelling error. Your present model appears to neglect (variations in) latency, assuming the server sees the events with the same (relative) timing as the clients. Even with perfect math, simulating the movement one fixed step longer / shorter because a packet arrived early / late is enough to break synchronization. \$\endgroup\$
    – DMGregory
    Commented Apr 19, 2019 at 15:36
  • \$\begingroup\$ How would I go around and fix that? Is the approach good? \$\endgroup\$
    – XverhelstX
    Commented Apr 19, 2019 at 16:12

1 Answer 1

3
\$\begingroup\$

The server, as you probably know, is the one source of the truth in a game architecture like you're creating. The server is calculating "the truth" of position based on input to the clients, then communicating that data back to each client.

Every time the server sends an update, each client should set positions of objects to what the server has shown. In other words, the server's new position data should completely overwrite the client's position data.

Then to keep things looking smooth on each client between server updates, the simulation on the client side should only be there to keep movement rendering smooth. So if the server were providing updates every 10 frames, it's up to the client to simulate the anticipated movement for the frames between each update.

With this approach, there is no drift on the client side, or if there is, it's very brief as it's only happening on the between-update frames.

It's not exactly an answer, but you might find this post somewhat relates to your question -> Lag compensation with networked 2D games

\$\endgroup\$
1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .