2
\$\begingroup\$

I'm trying to build a small networked game using WebGL and NodeJS. I have a basic client and server setup and I'm at the point where I'm trying to implement dead reckoning to simulate what happens on the client.

I have a odd problem which I'm not really sure how to fix, the game loops for my client and server don't seem to match up and the client one always seems to be faster. I'm hosting my server on the same system as my client right now and I'm logging every frame for the two. If I log it for longer than 5seconds the server starts to get behind by 10-20 frames and the gap just gets bigger and bigger over time. There isn't really anymore processing that is happening on the server than on the client at the moment because I'm working with a really basic example right now.

My loop for both right now look something like this:

var loopDelay = 16.666666666666666666666666666667;

function loop()
{
    setTimeout(function() {
        update();
        loop();
    }, loopDelay);
}

On the client I did have something like this:

function loop()
{
    setTimeout(function() {
        update();
        requestAnimationFrame(loop);
        draw();
    }, loopDelay);
}

But I removed it and copied the server one temporarily when I started running into this problem to make sure it wasn't that.

What can I do to make the two sync up perfectly?

Thanks

\$\endgroup\$
2
\$\begingroup\$

It's hard to tell for sure from the information given but it sounds like what you are trying to do is make the client and server run deterministic code such that if they start with the same starting state and process things on the same loop numbers that they will result in the same values for the same calculations. Is that correct?

One thing you are doing correctly is that you seem to have an update function that doesn't use elapsed time to do calculations (like how far something moves). That makes it frame rate independent which is important for preserving determinism.

However, it looks like you are relying on server code and client code to come up with the same results for the same code. That is tricky to get right using floating point math, and I believe is impossible if you ever use things like sine and cosine.

The way this is usually done is by implementing fixed point math using integers only. I haven't seen anyone do that in JavaScript. I don't run in JavaScript circles so it might be common, but I'm not sure.

Anyways, you are going to have a heck of a time making sure client and server always match up, even if you find a way to share code between the two without copy/pasting code or implementing every feature twice (both of which are error prone and make a lot of work!)

I think your better option would be to have one side (client or server) be authoritative and have the other side interpolate between data it receives.

In games with a low number of players in a match (like an fps where you can have up to 16 players), the server being authoritative is pretty reasonable and is more secure against cheating.

In games with high player counts (like MMOs), its usually the client that is authoritative believe it or not, and the server just makes sure a player isnt moving more quickly than they should be able to, jumping higher than they should etc.

Let's say he server is authoritative. You could have the client use dead reckoning and also player input to guess where things are going to be and extrapolate data. When the server sends an authoritative answer about these things though, the client would either need to "pop" the values to the right values or blend to the right values over a short amount of time to hide the fact that it was wrong.

Another way though would be for the client to be one simulation frame behind the server, so it always has knowledge of the last and next frame of data, and it can interpolate between those sets of data. Going this route, there is no wrong extrapolated data, but there is some input latency added. (Which you can again hide with client side prediction to get a blend of the two solutions!)

\$\endgroup\$

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.