Multiplayer desync

Recommended Posts

What am I doing wrong here. Normal movement is fine, but when boost is applied, there is rubber banding at the end.

I'm using client/server model to implement movement.


pseudo code:

Client sends inputs to server

Client process inputs and displays locally

Server receives inputs and calculates where client should be

Server emit client coordinates

Client receives update and applies coordinates

Client reapply all inputs made after the last server update


Player class: https://github.com/GodsVictory/SuperOnRoad/blob/wip/public/js/player.js

Server code: https://github.com/GodsVictory/SuperOnRoad/blob/wip/server.js

Share this post

Link to post
Share on other sites

server.js line 55: You use for loop, but then use `inputs.shift()`, which manipulates the array in place. Maybe it's different in JS, but you probably want to use `while(inputs.length > 0)` instead of the for loop. Otherwise you might have issues once there's more than 1 input at a time.

I strongly recommend to refactor the code, so that game logic that's shared between the client and the server is separate and shared. You should use the same code to apply update on a player instance on both. This removes code duplication and down the road will save you lot of headaches (that code duplication almost always causes).

On the client side you cache all the inputs in `updates` array forever it seems. There's no reason to keep the confirmed inputs, they can be thrown away. I suggest using some big enough circular buffer instead.

As for the actual trouble you have: I'm not 100% sure, at first I thought you weren't properly syncing the `lastBoost` variable, but that one is part of the inputs (which might not be a good idea either, see below), so it should work properly. The only thing I noticed is that it seems you apply the last input twice on the client. First you push it to the `updates` and then you iterate all updates and then once again apply this latest `data` update.
Maybe this isn't the cause of the issue, but certainly something to check. I recommend inspecting values and trying to find out at what point the reconciliation result becomes different than expected.

Regarding sending `lastBoost` and `time` as part of the input data to server: If the server is supposed to be authoritative, all that should be sent are the inputs and the server should simulate it all. Otherwise what stops me from saying my `lastBoost` time is constantly 0 even though I am boosting? Even the delta time shouldn't really be sent, although that is a design decision that might be needed if you need perfect reconciliation results. I do in my game and I went about this in a slightly different way (constant timestep).

You can read about my approach on my blog: https://antriel.com/categories/multiplayer-platformer/. While it doesn't yet solve all the issues like time synchronization and entity interpolation, that article should come next week :)

Share this post

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.