Multiplayer syncing logic

Started by
6 comments, last by Silenex 12 years, 10 months ago
I'm a fairly experienced programmer, but not too much of a game programmer, but I'm learning..

I'm developing a simple tile based game demo. Players can move from one tile to the next, but can't be between tiles. There's a smooth animation between tiles of about 500ms.

The problem comes when implementing networking to the game. Imagine a client gets a message to move a certain player to some tile, and then it gets a message to move that same player before the previous movement is completed, even if only a few ms before it's done. What's the typical approach to mitigating these differences?

Previously I attempted a type of "action queue" system. Where actions of stored in a queue and played one after another, but I'm unsure if that's the best approach. I ran into some troubles with it, so I'm assuming it's a bad idea.

What's the typical approach to mitigating small differences like this?
Advertisement
I can think of a few possible solutions, but I don't feel like any of them are the best solution. I'm just not sure. Here are a few of my ideas:

When a new movement command comes in, regardless of the current position of the animation just put it at the end. This might make animations look broken even under short periods, I'm not sure.

Similar to the last one, except just speed up the animation. This seems like a bad idea.

A queue where each animation is completed in its own time and the next one played afterwards. The only problem I see with this is if things get very backed up the user could be seeing things potentially seconds in the past, which isn't very good.
The client must keep up with the server, or the player will make judgments on out of date data and will become frustrated.

A simple solution is to speed up the animations. Snapping them in place will be quite noticeable, causing an unpleasant playing experience for players with latency. You can interpolate, if you're half way to moving the player north, and you get a request to move them West, then you have 500 ms to move them .5 north and 1 west, so you could devote 500ms * (1 / 3) moving them north and 500ms * (2 / 3) moving them west.

However you might still get some strange behaviour with such a scheme, depending on how you are set up. Is there an authoritative server? If not, how do you plan to prevent players from moving onto the same tile (assuming the game doesn't allow this)?

One option is to use lock step. Each client must agree on the next state before it is allowed to move. This way each client makes their moves at the same time. You can use predictive movement on the client to give immediate feedback when the button is pressed, thus hiding the latency involved in the clients coming to a consensus.
There is an authoritative server.

Is lock step common solution to problems like this? Or does it introduce too much latency.

What exactly is "predictive movement" can you explain the idea behind that?
If you have an authoritative server you don't need lockstep.

Just to mention that lockstep doesn't necessarily introduce latency. What logical frame rate does your game work at? If the logical frame rate is such that all clients can synchronise their decisions in less than the time between logical frames, then it won't introduce latency in the average case. If your game is logically running at 2hz, then lockstep would probably work.

Predictive movement (more commonly called "Client side prediction" if you want to hit Google) just means that the client assumes that actions are successful and immediately acts upon them. For example, if the player wants to move North, you start moving them immediately and shoot a message to the server indicating the request. If the server later responds with a message indicating the move wasn't successful, you revert the local player (again, you can revert them over multiple frames to make it less jarring). This results in a smoother experience for players.

The client can be even more clever if it is more than a dumb rendering terminal. For instance, it could avoid predicting (or even sending) movement requests that it knows will fail, such as moving into a wall. It can avoid (or delay) forward prediction if you are potentially sharing tiles with an opponent. For instance, if there is an opponent North-East, and the player moves North, don't start predicting until the server confirms you can move North, or you get a message from the Server indicating that the opponent is moving away from your selected tile. The client here tries to avoid taking an action that might fail, which would result in an unsightly "retraction" of what had previously looked like a successful movement attempt.

For non-tile based games, you generally can assume a lot less about the opponent (the information you have is almost certainly out of date).
The game has a fairly low frame-rate, about 10FPS.

Maybe I misunderstand what an "authoritative server" is.

In my case, the client is pretty intelligent, but the server ultimately has last say over everything. For example, the client keeps track of the map and determines where they can move. A client doesn't wait for a response from the server to tell it can move. If it thinks it can move, then it moves. However, the server will check that it can in fact move before it relays that command to the other clients.
It sounds like "play the animation faster" is the solution for you.

You appear to have an authoritative server, assuming that the server informs the client when it is rejecting a move request.
Now that I think about it, because most of the timing inconsistencies are likely to be very small, in most cases the compensation probably won't even be noticeable.

I'll try implementing this idea and report back how it goes.

Thanks for your help.

This topic is closed to new replies.

Advertisement