views:

606

answers:

4

There's a couple of questions here.

Imagine I have client A who's going to send the following message to Server: "START MOVEMENT FORWARD".

The server will not receive this message instantly, as there is a delay because of latency.

Question 1: ping (or better: round trip time) is the amount of time it takes for the client to send a message to the server and receive a response back. Does this mean the following if you can ignore the time it takes for the server to notice that it has received a message and start sending a response (this should be very short)?

  1. time it takes for client to send someting to server = round-trip-time / 2
  2. time it takes for server to send something to client = round-trip-time / 2

So, when client A sends that message, the server will supposedly receive that message round-trip-time / 2 milliseconds after the client has send the message. This leads me to the next question.

Question 2: should the client first send the package, and then wait round-trip-time / 2 milliseconds before actually executing that command client-side (in this case: move forward) to compensate with the latency/lag?

Now, the server will send the following message to all nearby players: "CLIENT A IS NOW MOVING FORWARD". These clients will then make sure that the character of client a starts moving, this leads me to the next question.

Question 3: should the client receiving the message that an other client has moved take into account that this message was send by the server round-trip-time / 2 milliseconds ago? So that the current time used for movement calculations timestamps should be reduced by round-trip-time / 2?

All these methods would in my mind make sure that synchronisation improves between clients, as latency is taken into account. Is this the right way of doing things? Do most other good multiplayer games do this? Any comments, suggestions, alternatives or random but related shouts that you'd like to give? Thanks in advance.

A: 

Some good multiplayer games uses a mechanism to allow players move smoothly even under heavy round trip times by allowing client to decide and send the position of the player to the server. There are fraud checking mechanisms but client is free for that. So if the round trip time goes wacko you see people jumping from place to place while you are moving smoothly. Even some MMO games take it to the next stage by allowing client to handle single player content without consent of the server. Only stats, battle reports and some other info is sent to the server along with few fraud checking data.

Cem Kalyoncu
I am doing just that. However, this issue is related to the position of the other players around, not yourself.
Tom
+3  A: 

I think that in most mmo's your client mainly moves without interaction with the server unless bad lag occurs. The server reproduces the movement with the help of the messages the client send to the server. So if for example the server lags, the client will stop recieving feedback from the server and revert to the position the server determine that you are at. That is why you jump back several frames during bad lag. This way the server will also have control over your speed so that you are not speedhacking. If your client moves at a certain rate which is over the speed determined by the server, you would simply jump back the extra frames.

Other clients would not let you move at all without response from the server within a certain amount of time. This is the times you would experience 'freeze-lag'.

Of course there are also occurences where the server simply take the position sent by the client and blindly trusts it. These are the games that are generally vulnerable to teleport hacks.

When it comes to the position of other players there indeed is a delay, which can be seen if you take two computers, connect to a game such as wow and move the two characters simultaniously. You would see that on both computers the non-local character will start moving after you really started moving him.

The client usually have some sort of lag compensation. So if another player is moving at a certain direction and then stops, your client will still simulate the movement of that player until you recieve a message from the server that he changed direction or stoped moving. That is why other players can jump back and forth when the ping is high. This is also why players can seem to just slide/run/walk away when you hit lagspikes and then return to their real position when your clients recieve positions from the server.

Of course this changes from engine to engine but it's a rather general aproach.

Edit: Forgot to add that it is very common for the server to also use lag compensation. If you hit someone in a mmo that is in range of you, that person might not be in range from the servers view. So the server takes the latency for both your clients and tries to match up if you were really in range of eachother or not.

Jonas B
Notice that I am not asking what kind of movement system or algorithm many games use, I've discussed this is an other thread. The main issue here is whether latency should be taken into account for movement calculations (done either client or server side), and if the assumptions I made were true. Upvote for trying to help regardless.
Tom
this is an = this in an*
Tom
Sorry for the misconception.My two cents are that you should at least use latency compensation on the server side, to make it fair for people with high latency.A good way to implement it however, is not something I'd be qualified to answer.Good luck and I hope you'll find what you're looking for eventually.
Jonas B
+1  A: 

for Q1: that looks right to me.

Q2: The way I've done this in the past is: if you want things to feel responsive, start executing the action instantly on the client's simulation, then the server simulates forward in game-time when the person initiated the action. i.e. the client knows at what ms in the game-simualation time it started, so the server can start it at that time also (note: this is always backwards in time from the server's current tick, so you have to save state back in time to do this).

Q3: the clients only really need to know that they are simulating at time X, and the server says the set of events {A,B,C} happened at times {X,Y,Z}. Then client and server can simulate forward with the same info and generally stay in sync (except when simultaneous conflicts occur). In those cases you have the server re-sync things so you usually end up within a pretty tight margin of error and a mostly smooth experience.

If your goal is to improve a perception of latency you might also just try trusting the client.

aaron
so the server would have to know the client's round-trip-time at all times? also, how would you store the X,Y and angle of every ship for every moment in time? And, how would you calculate such thing when the ship has been rotating in the meanwhile?
Tom
Latency doesn't matter because the client and the server both sim forward in a shared timeframe. so if the client says 'at time 5 I jumped', the server can sim that at event at time 5 correctly.Q2: For storing data: just have multiple copies. Compared to your mesh info, or game data, your dynamic info is tiny.Q3: Determinism and conflict resolution. sim forward in time. If players A and B interact, resolve and correct clients. if no conflict: server and client are automatically in sync.
aaron
A: 

This is an old question but I've worked out similar code recently so maybe this will help someone.

Yes latency is always useful in the calculation. But it is slightly more complex than RTT. Round trip time is always changing... your network code can keep an average, but the variance from that average is large.

The local client, remote client, and server all predict the current position using algorithms. The following data is close to typical:

  • Time: t
  • Placement: Position (x,y,z) and Orientation (x,y,z,w)
  • Movement: Linear movement vector giving direction with length as speed (x,y,z), and rotational movement vector giving axis with length as rotational speed (x,y,z)

You need the algorithms that extrapolate from a [T,P,M] set to the simtime. I won't be providing those here.

When the client registers a change in the drive of the ship at [T,P,M], that wont get to the server until T+deltaT. But if deltaT is within the tolerance of typical network latencies, the server can say "Yes it happened at T, I accept that." Otherwise it might want to correct the client saying "No thats out of tolerance, it happened at my time T' " in which case the client will have to REPLAY all the subsequently driven [T,P,M] changes from the server's corrected one (meaning you need to keep a queue or list of them).

The next client will get it at T+deltaT+differentdeltaT. It can't possibly change what it has already simulated, so if it isn't delaying it's simulation it will jump the remote ship and you will see a jerk frame. That's why remote driven ships should have their simulations delayed by a time consistently greater than 2*typicaldeltaT. It should be a constant delay, or a delay that changes gradually, and in times of severe lag you will see jerk frames nonetheless

You can smooth all jerks with extra smoothing code but don't do it until your code is otherwise flawless because it will just make it impossible to see where the problems are.

You must have a good synchronized time reference. A lot of code out there does it rather sloppily (e.g. RakNet doesn't (or didn't) do it very well). Here's a good hint: in the short run you can presume that everyone's clocks are running at the same rate, and you only need to figure out what the offset is, so keep a window of maximum and minimum offset and close it as you learn; In the long run you need to compensate for clients whose clocks are running fast or slow, so allow the window to open if you know for sure it must. You must use a local timesource that is monotonically increasing and not keyed off of the processor speed (which nowadays is variable).

No, don't delay the local simulation when the local "avatar" moves. It would seem way too unresponsive. You could delay it slightly (up to maybe 50ms) to help improve synchronization, but a delay all the way out to the RTT would make your game seem frustratingly unresponsive. Set an option for local delay and play with it, because a small consistent delay can be acceptable and improve synchronization. But it's not necessary and can cause lots of problems so I recommend doing that code last. (If you are trying to do a FPS melee game, you'll need to do this and all the other help you can get).

As for cheat prevention vs. simulation smoothness: First, the clients shouldn't just extrapolate from the last known position, when the official position changes. It should register an adjustment vector and slowly move from the old path to the new path for smoothness (but like I said above do this code last or it will mask other bugs). Secondly, the server should tolerate a wide range of delays... even on machines on the same ethernet the packet delay typically runs 5ms to 100ms or so... that is quite a range. Of course you need to cut it off and say "if you say you moved at time T but I got the packet at T + some_large_number then I think you are trying to adjust the past and lying to me." some_large_number shouldn't be much bigger than the average RTT to keep people honest.

The simulations will never be tightly synchronized. They should stay within 400ms or so over the Internet but certainly will stray outside of that during times of lag... to 30 seconds or more, and you need to tolerate things that that because they aren't rare. Given that the Internet is limited by the speed of light in copper, you can always expect one-way latencies to typically be in the range of at least 100ms minimum for your far clients, often 500ms or longer.

Therefore I highly recommend you don't try to make a melee FPS game over the Internet (some big companies try but will always have troubles). There are tricks you can do if you are using projectiles (by running them fast in one simulation and slow in the other) so that even though the timing is off, it looks on. Also, FPS games use the rule that hit-detection is based on the attackers simulation... it feels more wrong when the attacker knows he was dead on target and misses, then when a defender knows he was out of the way and gets hit anyways. You have to choose one or the other, and psychologically that's how it's been done. Melee requires a level of synchronization which is frankly impossible and most game companies won't touch MMORPG FPS melee but rather use auto-targetting (try playing Mortal Online, you will see what I mean).

Good luck.

Mike Dilger