Simulating Lag and Drop when Debugging Multiplayer Games

Debugging multiplayer games locally

These days, I’m playing around with making online multiplayer prototype games.

Most of the time, when we debug our video games for online multiplayer, we run a local server on localhost. This server acts as:

  • a file server - sending the game files to the client,
  • a game server - transferring information between clients, authorizing transactions, etc.

You can debug your code logic on server side and client side very easily nowadays. For instance, I use VS Code, with NodeJS to debug the server side and the Chrome debugger plug-in to debug the client side.

However, once your game works perfectly with your local server, it only means that it works perfectly with perfect network condition! You are still miles away from having a game working in real world network conditions.

When released, your multiplayer code will have to deal with:

  • variable delays of communication between clients and server,
  • variable number of dropped messages/packages.

Although software like Unity offers to simulate this kind of disruptions, we are not all and/or always using Unity :D ! I am using Phaser right now. After some research I found a little piece of software allowing to simulate real-word network condition locally, so I thought I will share.

Clumsy an utility to simulate broken network

This piece of software is named clumsy and can be found [here] (https://jagt.github.io/clumsy/). According to their website:

clumsy makes your network condition on Windows significantly worse, but in a managed and interactive manner.

What’s nice about it is that it does not require any installation and works out-of-the box. When unzipped, clumsy sits next to a file config.txt where you can specify exactly which part of the network you want to disrupt.

For instance, if I host my server on localhost:5000, I can make a configuration that disrupt the access to localhost:5000. To do so, I added the following in config.txt:

HTML5 games: outbound and tcp.DstPort == 5000

After that, when you open Clumsy, you will be able to select the configuration HTML5 games from the droplist menu.

Note that the configuration localhost ipv4 all does roughlythe same as my config except that it disrupts any local hosts.

Experimenting with Delayed and Dropped Packages

To give you a better idea of how network dirupstion translates into your game, I tested clumsy on a prototype I made recently. I used a client authoritative network with two clients and one server to keep things simple.

What I mean by Client Authoritative is that:

  • Client 1 (on the top) applies the input of the player without delay,
  • Client 1 sends the position of the charactor to the server,
  • The server transmits the position to Client 2
  • Client 2 (on the bottom) applies the position

Basically, the server does not nothing but transmitting information between Client 1 and Client 2. Obviously, in practice, you would not do that to avoid cheating, but that ’s ok for our example.

Without delay and with 0% of dropped packages, the game works like a charm. However, we have no feel of what the players will be experiencing.

When we add some delays (1000 ms), the game still works, and we can test how the game feels with the server-to-client delay. However, clumsy’s delays seem to be fixed, as opposed to be random, which is most probably the case in real network.

With random delays, you would experience bugs if your code relies on messages arriving to the server in the order they have been sent. For instance, something like that would lead to bugs:

[Client Side]

this._socket.emit('spawning_points_request');
this._socket.emit('new_player_request');

self = this;
this._socket.on('spawning_points', function(data){
            self.spawning_points = data.spawning_points;
        });

this._socket.on('new_player', function(data){
            self.addPlayer(data.player, self.spawning_positions[0]);
        });

In this code, the spawning positions must be received from the server before that the new player is received. While we requested the spawning positions first, a real network would not guarantee that you will receive the spawning points first. If I understand well, in clumsy, you can emulate that behaviour with the Out of order option.

Finally, when we add dropped packages, things can become a big mess. In our example, Client 2 (bottom) always succeeds to catch up with Client 1 (top) because Client 1 sends the position of the character and not the change in position.

However, if your code relies on sending changes in state (i.e. delta method) or on sending an important message, you may experience bugs as these messages are dropped. For instance, in this simple example, I only send once the message to request a new player to the server. If it does not reach the server, I need to reload the page, until it does!

Hope you will have fun debugging with clumsy. If you know other useful tools for debugging multiplayer online game, let us know in the comments below!


Also in Recent Posts

comments powered by Disqus