3
\$\begingroup\$

I have read plenty of articles about multiplayer principles and I have basic client-server system set up. There is however one thing I am not clear on.

When player enters input, it is sent to the server and steps back in time to check if what should have happened at the time of that input and it resimulates the world again. So far everything's clear.

All articles took shooting as an example, because it is easy to explain and it is pretty straightforward, but I believe movement is more complicated. Imagine following situation: 2 players move towards each other.

A------><------B

Player A stops halfway towards the collision point, but there is lag spike so the command does not arrive on the server for a second or so. Current state of the world on the server (and on the other clients as well) at the time when input arrives is this:

[1]:

-------AB-------

The command arrives and we go back in time and re-simulate the world, the result is this:

[2]:

---AB-----------

Player A sees situation [2] which is correct, but the player is suddenly teleported from the position in [1] (center) to the position in [2].

Is this how this is supposed to work? Point of the client prediction is to give lagged player feeling that everything is smooth, not to ruin experience for other players.

Alternative is to discard timestamp on the player's input and handle it when it arrives on the server without going back in time. This, however, creates even more severe problems for lagged player (even if he is lagging just a bit)

EDIT:

To give you more info about my situation, I am making a game where exact position is quite important and the action is quite fast-paced. Imagine air-hockey with some perks on top. Another thing worth considering is that this is flash game and I have to use TCP. From my previous experience, ping times of 200ms are the norm (unlike 50ms on pc games) in situations I will be facing.

\$\endgroup\$
1
\$\begingroup\$

You seem to have explained everything yourself. But, in case you need someone agree / disagree with that: Yes, your thoughts all seam reasonable.

As you do not wait for all players inputs before start simulating the world, you will run into those problems. You can not solve this, as you don't have the information (what each player does) before the network has transferred it.

So you only can "guess" what will happens and show this to your players, which is like predicting future (you might have luck or not). Or, you show only what is already for sure which will cause the maximum lag of all users to effect all users experience.

The only thing you can do about this is to improve your prediction algorithm for a user. E.g. detect movement patterns in acceleration, deceleration. But you'll never get it to perfection...

Note, that if a user only pretends to be lagging (network lag) he might see his "simulated" future. So the user might cheat. To balance the chances, you should delay the information (what other players did) sent from the server to each user by the detected lag (minus the minimum lag of all players).

EDIT #1

To answer your question in the comment below:

Well, the question might be hidden in there, but I wanted to ask is which approach is better, to re-simulate world on the server when user's input arrives or discard the timestamp info. Both have their pros and cons, I guess it depends on the situation. I was just wondering if there is another solution that I might be missing –

In the environment of a 3D-Shooer game:

  1. Dropping the Timestamps: This is bad for the player with longer lags, as something different happens than he actually commanded. His commands will be executed in the future. You stop pressing "forward" and your actor stops some time later. You maybe shoot while seeing the object in the cross hair, but its executed when it already moved further. The players with longer lags know this and can adapt to this. They can release the forward key earlier or shoot a bit earlier than they would normally need. This is like driving a car, where you need to turn the wheel some meters in advance if you drive very slow... This is in a way acceptable to the lagging player, as he knows that he causes the problem himself. He also cant cheat by even increasing his lag.

  2. Simple Re-Simulation when releasing information immediately: This is bad for all players with fast connections, as the lagging players just "beam" from one position to the other and they don't have a chance to know where he really is, while the lagging players can more easily aim their targets (they immediately see their correct opponents positions).

  3. Delayed information releasing: You can also wait until all clients have send their current "actions" to the server and then distribute the whole information to all clients and simulate it. This gives a consistent state of the game at all clients, without the need for re-simulation. The client programs may of course "predict" the future and display it. This causes all players to suffer from the largest lag, but equalizes the chances of the players a bit. The lagging players still have some more problems, as their update-interval is longer. This means the time needed to send the next update from the server to this client is longer, and the player has a longer time in which he only sees the "prediction". But as long this period is short enough, this shouldn't be a real problem.

You can also do a combination of these methods. You can delay information releasing up to some limit (e.g. 50 ms and then start to drop "timestamps"). So you wait until all players have send their next actions -or- some timeout (e.g. 50 ms) is reached and then distribute them to the player together with the timestamp registered at the server. The server just simulates this. If an action is arriving too late at the server it is executed within the next round / simulation tick. The result is, that up to the limit (e.g. 50 ms) the player will have a synchroneous play, the server does not need to resimulate and only players with longer delays will have re-simulations at their client and will actually suffer from the problem. It also enables to have a quicker update period, if all players have a shorter ping that the limit (e.g. 50ms).

Other Game Types...

In games which are more cooperative in nature and lots of players (as MMORPGs for example) the lag for all other players should be at least be limited to a reasonable amount. You'll always have players with slower connections, so they would at the end define the speed of the whole simulation. Depending on the type of game, the acceptable lag can be up to 400ms without being noticed by the players. This might especially work for real time strategy games... Especially in real-time strategy games repeatedly re-simulating and excessive "beaming" of actors would not be acceptable, if this is happening for all players. "What happens if I delay commands for x milliseconds in this game?" is what matters. For example in a real time strategy game it would even sound logical that it takes some time to tell the acting unit what it shall do, then it maybe needs to plan the route and finally starts walking. So a short delay won't disturb to much.

\$\endgroup\$
8
  • \$\begingroup\$ Well, the question might be hidden in there, but I wanted to ask is which approach is better, to re-simulate world on the server when user's input arrives or discard the timestamp info. Both have their pros and cons, I guess it depends on the situation. I was just wondering if there is another solution that I might be missing \$\endgroup\$ – Lope Nov 7 '13 at 15:54
  • \$\begingroup\$ I edited my answer according to your more clear question... \$\endgroup\$ – SDwarfs Nov 7 '13 at 17:02
  • \$\begingroup\$ "You can also wait until all clients have send their current "actions" to the server" - this could work only if client sends the update each "tick", or am I missing something? I can't wait for all players if I do not know who's input changed. And sending client state every tick seems like waste of bandwidth (which is far from free :) ) \$\endgroup\$ – Lope Nov 7 '13 at 17:48
  • \$\begingroup\$ In that case all players MUST send their actions for each simulation step that is executed by the server. If a player does nothing the client just sends a packet with "no action" or "continue as before". So your server knows when it received the actions for the next simulation round. To reduce traffic you can of course also collect the actions for multiple simulation ticks at once (e.g. every 50ms). \$\endgroup\$ – SDwarfs Nov 8 '13 at 10:09
  • \$\begingroup\$ my tick is 50ms long :) I am using fixed time step and interpolate in between. Grouping commands further doesn't seem like good idea. I suppose I will have to try something else, probably re-simulation \$\endgroup\$ – Lope Nov 8 '13 at 10:14

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.