6
\$\begingroup\$

I am trying to understand how networking in games work as I am trying to make an online game myself. I can't grasp how it is possible to synchronize the players, in order to make the game deterministic. I found an article saying this:

in order to ensure that the game plays out identically on all machines it is necessary to wait until all player’s commands for that turn are received before simulating that turn. This means that each player in the game has latency equal to the most lagged player.

This makes sense and I also came to the same conclusion after hours of drawing graphs with various scenarios. However, there are some games where one player can have 500ms delay, and another player could have 40ms delay. In this case, how is the game deterministic ?

Lets name players with 40ms, 500ms delay: Player40, Player500

Lets say that Player40, shoots Player500 with an instant laser shot at T1 = 0ms. Exactly 40ms after the Player40 actually clicked with his mouse to shoot (so T2 = 40ms), The "laser shooting event" registered on the server and returned "ok, you can execute laser shoot" to Player40. So, the shot is being applied on Player40's machine and on his screen he sees that he killed Player500, and the corpse is lying on (x1,y1,z1).

Meanwhile, what happened on Player500's machine, was that Player500 was running straight. A few moments later he sees a laser a few feet behind him, he dies even though the laser didn't hit him, and his corpse is lying on (x2,y2,z2).

Since this scenario never happens in some games, does this mean that those games are deterministic ? How is something like this possible, without forcing all players to get a delay equal to the delay of the most lagging player ?

\$\endgroup\$
  • \$\begingroup\$ "It is necessary to wait until all player's commands for that turn are received before simulating that turn." means the laser shot doesn't happen until everyone's received it. That means at least 540ms (if that's the delay between the players) after Player40 clicked their mouse. Likewise, Player500 didn't start running straight until at least 540ms after they pressed their forwards key. \$\endgroup\$ – immibis May 20 '15 at 5:23
  • \$\begingroup\$ @immibis he was running straight this whole time \$\endgroup\$ – dimitris93 May 20 '15 at 5:24
  • \$\begingroup\$ @Shiro I forgot to note, you should use TCP at least for the building of a lockstep framework so you can circumvent packet loss and other things that will bug you. As for Player500 running straight the whole time: did you send a command to tell Player500 to stop running? \$\endgroup\$ – JPtheK9 May 20 '15 at 17:35
  • \$\begingroup\$ @JPtheK9 I think i'm gonna use lidgren library. I don't understand how "you should use TCP at least for the building of a lockstep framework" translates into code. \$\endgroup\$ – dimitris93 May 20 '15 at 19:25
5
\$\begingroup\$

It's actually the other way around. Games are made deterministic to be online.

The basic idea is to send commands rather than game state. If you have a function F(X) = Y and you need everyone's Y to be the same, you can send X instead of Y. The reason why this happens in the first place is because sometimes commands are more efficient than game states bandwidth-wise. In an RTS game, there can be 200+ units at one time so sending a command is better than replicating 50 positions, rotations, healths, etc.. There are several other benefits like 100% game state cheat proof and small replay sizes.

Unfortunately, deterministic games require deterministic simulations which floating-point numbers cannot do for you. This means Box2D, PhysX, and Bullet are all out of the window without clever floating-point tricks, but even with those low-level modifications, they can't be cross-platform deterministic.

Fortunately, you don't have to code your own physics engine or lockstep logic if you're using Unity. I'm working on a deterministic physics engine with lockstep multiplayer, all integrated with Unity3D. If you'd like to sign up for the Beta and give it a shot, here's the link: http://forum.unity3d.com/threads/dphysics-beta-cross-platform-deterministic-physics-engine.318827/.

Sorry for the shameless plug :). Anyways, if you're not using Unity, I'll give you a few details about a lockstep framework that'll be good to know anyways.

Lockstep games think in frames, basically an integer that goes up every time the game is simulated. On frame 100, everyone's simulation should be the exact same but everyone doesn't have to be on frame 100 at the same time which is how latency is handled but I'll get into that more soon.

Everyone receives the same data for every frame as well, and can't advance to the next frame if they haven't received the data for the frame. A client has to have a packet designated for frame 100 to run frame 100. Inside this packet are player commands.

i.e.: Units {1,2,3,30,127} -> Attack -> Unit 10 or Player 5 -> Mouse Input Rotate -> (30,20) then Player 5 -> Shoot.

From there, you can adjust the simulation rate to be faster or slower depending on how many packets in advance you have to simulate. While others' response times don't really matter to a player, his own does. If a player has 500ms latency, he'll simply get packets 500ms later than everyone else thus his game state will be 500ms behind. The main problem is that when this player sends a command, he won't be getting it back until 500ms later which means his actions won't be responded to for a noticeably long time. This is true for authoritative server setups as well. Lag masking methods can be used like pre-played animations, instant sounds, slow acceleration, or "fake" movement.

This is the core of DPhysics Lockstep. If you're not using Unity, you could take a peek at the code anyways to see an example implementation. The DPhysics implementation uses a server instead of P2P which means no desyncs or funky code and latency is determined by a single source instead of by the slowest players.

\$\endgroup\$
  • \$\begingroup\$ 1) You say Everyone receives the same data for every frame as well, and can't advance to the next frame if they haven't received the data for the frame, if that's true then every player would have the max delay of the players ? 2) How does this logic apply to the specific example I posted above ? How one player with 40ms shooting a 500ms player, doesn't cause weird behaviors without player40 getting 500ms delay ? \$\endgroup\$ – dimitris93 May 20 '15 at 5:14
  • 1
    \$\begingroup\$ Let's say the server's frame is the Master Frame (MF) and the simulation frequency is 1ms. In this example, MF = 1000. Player40 shoots. Command takes 40ms to travel to server so MF is now 1040. MF now distributes this to Player500 who is 500 frames behind to accommodate latency. Player500, at 540, gets the data then simulates it. Meanwhile, 500 frames have advanced (the time it takes for data to get to PlayerB) so Player40 is now at 1040 - 40 + 500, 460 frames ahead of Player500. If Player500 died from that command, he would now be dead NOW on his client and 460 frames ago on Player40's client \$\endgroup\$ – JPtheK9 May 20 '15 at 5:25
  • 1
    \$\begingroup\$ The article was referring to P2P where players send their commands directly to other players. DPhysics uses a server so the lag is that of the client being measured only. Player40 sending a command to the server then getting it back takes 40+40ms, not 40+500 or 500+500. In P2P, every client has to get a frame from every other client which is why the lag is that of the most lagged player. In the case of P2P, Player40 now has 500 ping because Player500 is one of the many servers in the game, and Player40 must get a frame from all servers. \$\endgroup\$ – JPtheK9 May 20 '15 at 5:29
  • 1
    \$\begingroup\$ League of Legends isn't lockstep but I don't know exactly how League works because they haven't talked too much about it. My guess is League uses an authoritative server and syncs the gamestate of the simulation. This has the same problem as lockstep in that data needs to go to the server then come back. \$\endgroup\$ – JPtheK9 May 20 '15 at 6:41
  • 1
    \$\begingroup\$ @Shiro It's probably using the simple client-server model - that is, when you right click, the client sends a packet saying "Hey, I right clicked here" (or "Hey, my character wants to move here") and the server sends back "Okay, your character is moving here". The advantage of this: no desyncs, ever. The disadvantage: latency. \$\endgroup\$ – immibis May 21 '15 at 2:46

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.