The Netfix and its Impact on Legions

1. Introduction

So there has been a lot of talk about the netfix and a lot of (uninformed) talk about what it means.  I'm going to try to clear up what exactly it is and what it actually means for the game. Due to the nature of the topic this will get a little technical.  I'll try my best to explain everything clearly, but be aware there's only so much I can simplify.

2. Background

To understand what the netfix is one must first understand a bit about how games are simulated.  There are lots of ways a game can run, but we'll assume we're going to talk about a game like Legions (which is the simplest and most secure model for a multiplayer game).  The game world you move around is a collection of objects that are updated in discrete calculations called "ticks".  This means that there are a finite (and consistent!) amount of positions a person is in each second, this is important and we'll see why later on.  The tick rate of Legions was 1 tick every 32 milliseconds, or 31.25 ticks per second.

The game uses what's called a client/server architecture.  This means that there is one server that has the authoritative simulation that determines what happens in the game.  So each tick the game will do a variety of functions.

A client will collect its input and then send it to the server.  A server will gather all the input packets it has received, react to this input by spawning projectiles or applying forces to their player or camera, check for collisions with objects, correct positions based on said collisions, and move all objects according to the forces acting on them at the time.

3. The Problem

3.1. Projectile Movement Delay

So as it was Legions had a few nasty little bugs with the way it handled updating objects.  When a new object was created it would not be updated immediately.  Instead it would be added to a list of objects to update, and would be updated the next time the server tried to update its objects.  This would create a lag between the time a projectile was fired and the time a projectile would start to move.  This essentially added 32ms to everybody's ping.

3.2. Packet Queuing

Legions also had a nasty bug in the code that would send packets over the network.  The game would send packets in an inconsistent fashion, instead of sending a steady stream of packets it would (not really) randomly queue a packet to be sent on the next tick.  This meant that packets would be sent at an inconsistent rate (1, 0, 2, 1, 1, 0, 2, 0, 2, etc) which could be devastating, especially with packet loss.

3.3. The Tick Rate Itself

Finally, the tick rate was pretty slow given how fast the game is.  Players can move fast enough that their collision boxes aren't contiguous volumes, this means that you can miss a player by shooting in the space between where they would have been had the simulation been more detailed.  More on this one later.

4. The Solution

4.1. Process Objects Immediately

The first fix is a pretty obvious one.  Instead of adding objects to a list that will be executed  the next tick, we can process them at the end of the current tick.  This is the fix that contributes the most to having to aim behind you to rocket jump.

4.2. No Packet Queuing

This one is  an easy fix as well!  The netcode for legions was designed for the days of 56k, which have (thankfully) long since passed.  We have much higher throughput now, and we can afford to throw way more information over the pipes and still come within a reasonable amount of traffic that can be handled by a lowly DSL line.  We simply bypass the queuing logic and send packets without worrying about not sending too often.

4.3. Speed Up The Tick Rate

I decreased the tick interval from 32ms to 15ms.  This increases the number of ticks per second to 66.66 (repeating).

5. The Effects

5.1. Projectiles Feel Good

Projectiles actually feel (and look!) like they come out of your gun.  They behave more "as you expect" and go more "where you want them to".  Midairs are way, way easier, chaingun doesn't look like it's coming from way behind you.

5.2. The Game Is More Consistent

Both your client and the server would suffer from the queuing issue, and at different times.  Shots happen when you expect them to more often.  The human mind is pretty bad at picking out exactly when something's not immediate, so this one is really hard to pin down.  This certainly makes the server simulations behave better and helps with "non-regs" when trying to body-block somebody or dodge a body-blocker.

5.3. Everything

Oh this one is really my favorite, I don't even know where to start.  There are lots of interesting properties that this one has, lots of them having to do with interaction with netcode.

Speeding up the tick rate actually makes the game feel significantly different because of the relatively unsophisticated and shoddy physics code.  The game feels significantly less "floaty" and more "immediate" because it has more accurate representations of acceleration (from your jets and from gravity).  The way that the math works out your jets will push you farther faster and gravity will pull you down faster.  This feels significantly more "real".

If you think back to the way that ticks happen you can see all sorts of nasty little edge cases that crop up.  Because of the (piss poor) way that collision is handled in the engine there isn't a unified step where you can test projectiles against moving objects.  Since objects moved in 32ms increments, you could quite easily miss a player if they had too high a transverse velocity by shooting the space between their calculated positions.  Giving the simulation a finer granularity helps to hide these issues without overhauling huge amounts of the game's collision code.

This one requires a bit more information about how players are displayed on your screen.  Your game tries to provide to you the illusion of smooth movement of other players by displaying players as moving between the last two positions you receive from the server.  You can see that this means that all player representations on your screen are delayed by at least 32 ms.  By reducing the tick time to 15 we halved that mandatory delay time and made players' representations more accurate and more resilient to network issues like dropped packets.

This also has a funny side effect of making your listed ping drop by 17ms.

6. So What Does This Mean?

In short, the game's netcode is now far more reliable, and the game behaves much more like it should.  I'd estimate that your ping has been reduced by ~30ms on movements, and ~60ms on shots, and non-registers should happen much, much less often. 

You're welcome!

7. Other Reading

For more information on the basics of game networking check out What every programmer needs to know about game networking.

For more information on why changing the timestep alters the physics so radically check out Euler's Method.  As far as I know Legions uses Euler's method exclusively.

Comments