GodsVictory Posted June 19, 2017 Share Posted June 19, 2017 Currently, when a client moves, the inputs are processed on both the client and the server which use the same calculation to process the movement. When the client receives an update from the server, the servers position will override the clients position. I would hope that the client and the server would calculate the same positions, but that is not the case. I believe timing is the culprit. What is the best practice when syncing movement? Current flow: Source: https://github.com/GodsVictory/SuperOnRoad ivan.popelyshev 1 Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 19, 2017 Share Posted June 19, 2017 It depends on application. In general case, the best way is to send every server calculated position and lerp the client position to it , not override it, but move it smoothly. For strategy games with a huge number of units you can use determinism, but that means you have to be sure that all operations, and especially, all floating-point operations are synchronous both on server and client. To check synchronization, you can compare hashes of client gamestate and server gamestate, its not difficult to send it every frame. I could post some books here but my dropbox library is already blocked by publishing houses. Really, I hate publishing houses. You can at least read some articles from https://0fps.net/ Quote Link to comment Share on other sites More sharing options...
Antriel Posted June 19, 2017 Share Posted June 19, 2017 What you implemented is called Client-side prediction. Gabriel Gambetta wrote a nice article about it: http://www.gabrielgambetta.com/fpm2.html I also wrote about how I implemented in my in-development multiplayer platformer game: https://antriel.com/post/online-platformer-3/ You also want to implement what Ivan mentioned: 22 minutes ago, ivan.popelyshev said: lerp the client position to it , not override it, but move it smoothly Basically, on the client, once you do the reconciliation, you calculate the error, i.e. the difference between predicted and actual position. But you don't apply this difference right away, but instead you apply it over a few frames. You can find some pseudo code for one way of implementing that in an article by Glenn Fiedler: http://gafferongames.com/game-physics/networked-physics/ Quote Link to comment Share on other sites More sharing options...
GodsVictory Posted June 19, 2017 Author Share Posted June 19, 2017 1 hour ago, ivan.popelyshev said: It depends on application. In general case, the best way is to send every server calculated position and lerp the client position to it , not override it, but move it smoothly. For strategy games with a huge number of units you can use determinism, but that means you have to be sure that all operations, and especially, all floating-point operations are synchronous both on server and client. To check synchronization, you can compare hashes of client gamestate and server gamestate, its not difficult to send it every frame. I could post some books here but my dropbox library is already blocked by publishing houses. Really, I hate publishing houses. You can at least read some articles from https://0fps.net/ 1 hour ago, Antriel said: What you implemented is called Client-side prediction. Gabriel Gambetta wrote a nice article about it: http://www.gabrielgambetta.com/fpm2.html I also wrote about how I implemented in my in-development multiplayer platformer game: https://antriel.com/post/online-platformer-3/ You also want to implement what Ivan mentioned: Basically, on the client, once you do the reconciliation, you calculate the error, i.e. the difference between predicted and actual position. But you don't apply this difference right away, but instead you apply it over a few frames. You can find some pseudo code for one way of implementing that in an article by Glenn Fiedler: http://gafferongames.com/game-physics/networked-physics/ I am lerping instead of simply overriding. I was just wanting the calculations to be more accurate between the server and client. The more you lerp, the less responsive the controls feel, but the less you lerp, the more choppy movement is. Quote Link to comment Share on other sites More sharing options...
Raggar Posted June 19, 2017 Share Posted June 19, 2017 You could take a look at how Lance-gg does it: https://github.com/lance-gg/lance By how much is the position 'off' compared to the predicted state of the client? I'm using pretty much the same code as yours for a project of mine(currently on hold). I'm sending the deltas to the server, but since both loops run (optimally) at 60Hz, this shouldn't be the issue, and both deltas should constantly be the same. You usually never really see the correction in multiplayer games. Only the occasional rubber-banding. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 20, 2017 Share Posted June 20, 2017 Btw, you posted it in pixi.js section you're just lucky that I know that stuff and some people are jumping all over the forum. Quote Link to comment Share on other sites More sharing options...
Antriel Posted June 20, 2017 Share Posted June 20, 2017 8 hours ago, GodsVictory said: I was just wanting the calculations to be more accurate between the server and client. They should be pretty accurate most of the time. As far as I can see the errors come from either: Floating point operation errors. Those shouldn't even be visible unless they resulted in widely different results, like getting stuck on an edge vs moving alongside it. Not much you can do about this, but it should be extremely rare. Too active physics environment where the world state is too different between client and the server. Not much you can do about that, other than increasing tick rate. From what you said in your first post you shouldn't have issues with either of those, so I maybe you implemented the prediction wrong. Are you correctly reapplying unconfirmed inputs on the client (i.e. properly calculating reconciliation result). Are you using the same timings on both client and the server? Usually you should use fixed time step, not really the time it took for the packet to travel (i.e. not the time since last input). Although that depends on the game and could work with high enough tick rate (small time step). Quote Link to comment Share on other sites More sharing options...
Skeptron Posted June 20, 2017 Share Posted June 20, 2017 Having different result on the client and the server is a bad sign, you are right to dig deep and demand perfect accuracy. Some of the things I did to make sure I had the same behaviour between the client and the server : Synchronize the clock between both ends, use a fixed timestep, and make sure they do the same calculations at the same time, over the same timestep Share the logic code between the client and the server (if they are both written in the same language). You'll avoid duplication and greatly increase accuracy Make sure the client has all the important state variables to run complete calculation. Don't forget to send velocity, gravity etc. if they are to change and needed in the physics calculation Round your results. In JS you'll have crazy-long floating points results, round them (two-decimal numbers are enough in my opinion, you could even go with one) If your game is deterministic enough you shouldn't even have to lerp. Client should have the same results as the server and thus almost never need correction (unless lag happens). Quote Link to comment Share on other sites More sharing options...
Taz Posted June 20, 2017 Share Posted June 20, 2017 1. The flow is more like this chart, with a time gap between when the client and server calculate the new position. To make it like your flow chart you would need to make the client wait 25 ms to apply the input if it takes 25 ms for the server to receive and apply it. If you want to keep the client-side predicting accurate then you need to predict and account for this delay. 2. Sometimes you can make it feel more responsive by triggering non-movement animation(s) right away, like rotating the avatar or part of it (head or eyes for instance) to face the new direction. Another thing you can try is to have the client change velocity more slowly - that way you can respond right away but the position won't get as out of sync.. 3. Are you maybe doing this sequence client-side: set to new position right away, LERP back towards the old position for awhile, LERP to new position? Quote Link to comment Share on other sites More sharing options...
GodsVictory Posted June 23, 2017 Author Share Posted June 23, 2017 I ended up fixing the desync issues. I wasn't reapplying inputs that were made after the last server update. A new issue has arose out of this, all normal driving is perfectly smooth, but boosting seems to cause desync. you can see the boost desync here: https://superonroad-wip.herokuapp.com/ At the end of every boost, you'll get rubber banding (WASD to move, space to boost) code: https://github.com/GodsVictory/SuperOnRoad/tree/wip Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.