

How does rollback netcode work in fighting games? And why is it so difficult to program?

The premise is simple: you have a video game with couch co-op (pictured) and want to add online multiplayer. Easy, right...?


Well, it's not so simple. If you send each player's button presses over the internet (shown in this post with big arrows), there's some delay due to how far the signal must travel.
So the inputs get out of sync between the two screens.
(Notice that the order of the characters jumping changes.)

...This out-of-sync thing is a problem because it can make a player succeed on one screen but fail on the other.
A few frames doesn't sound like a lot, but it can be the difference between victory and defeat in an action game.
E.g. Mario gets/misses the coin.


To address this, the next thing we could try is, rather than sending inputs over the network, sending states over the network.
That is, instead of communicating Player 1 pressed jump, the client instead sends Mario is at position X: 20, Y: 34, and has 5 coins and so on.
In this model, each client is responsible for the state of its own player.
At first, it looks the same as before...

...but since you're sending state data, both clients will agree on the outcome at the end.
Notice how Mario still hits the block and gets the coin on P2's screen - even if it looks janky.
This is why in Mario Kart, you can throw a green shell at someone but somehow miss.
Things can look weird due to the communication delay.

This system is exploitable. Each client is trusting the other client to provide accurate info.
If one player hacks the game, they can do anything they want, such as a fly hack.


One cop-out way to solve these problems: have P1 run the game on his computer, and just stream it to P2, Google Stadia style (rip).
It's impossible for P2 to cheat now, and everything is the same on both screens...
...but P2 gets tons of input delay now, since data has to make a round-trip before he sees the result of his button press. This is very unfair for competitive games.

Also, P1 can totally still cheat (but it might be more obvious to P2).


Let's try throwing money at the problem.
What if we create a server to mediate player interactions?
In this example, players send states (like we saw earlier), but now the server acts as a middle-man to make sure the states are legit.

Like before, state-sharing guarantees eventual agreement...

...but now, it's possible to protect against fly hacks!
The server can run code to inspect the supplied player states and notice any sus data.
If you've ever been kicked from a Minecraft server for flying this is why: the server has a check that trips if you're in midair for longer than you should be.

Unfortunately, servers are too expensive for starving indie devs (e.g. Nintendo), so it's worth exploring other options.

If you're making a fighting game, you don't want anything to look different across the two screens. Everything matters, down to the pixel!
Every method so far (except streaming) has failed to make everything line up the same on both screens.
Luckily, there are ways to achieve this! As a first attempt, what if we delay local inputs to match the delay of network inputs?
In other words, we make Mario's actions delayed on P1's screen, and we make Luigi's actions delayed on P2's screen.
Everything is in sync now!

...However, due to the extra input delay, Mario's timing is messed up. He now has to press jump earlier in order to hit the block.
This is a downside of delay-based netcode: your muscle memory for combos and techniques needs to change based on the current network delay.

On the plus side, notice that we're not sending any state data anymore - so there's no chance for a client to cheat the game by lying about the state data.
If you try to do a fly hack, the other player doesn't see the result; only button presses are being sent back and forth.

Of course, if the two games are different, they'll fall out of sync pretty quickly. P1 might win on his screen while P2 is still in the middle of the game.
If you want to detect this kind of desync you can send state data back and forth - but rather than using it to actually facilitate gameplay, instead just compare it.
If there's a mismatch, you know something has gone wrong. This could be from hacking, but it could also be a game bug.
Preventing these mismatches from happening is one of the challenges of this kind of netcode. The game needs to run the exact same on every player's computer.

There exists a type of netcode which prevents cheating like delay-based does, but does not have that nasty input delay.
Its name is spoken only in whispers.
Game devs shudder at the sound of it.
Its name is rollback netcode.
In rollback netcode, you're still sending input data back and forth. However, each input is sent along with a timestamp of when it was pressed.
When the input is received, the client calculates what would have happened if it had received the input on time. Then it skips ahead to that point.

To really show the effect, here's a gif with double the network delay.
Notice that, on P1's screen, Luigi skips ahead to the peak of his jump.
It's a lot like missing your cue in a recital and skipping to the middle of the song to get in sync with the others.
This teleporting effect is the main tradeoff of rollback: you don't experience any input delay on your own character, but these weird artifacts can occur.

Also, as a developer, rollback is pretty difficult to implement.
The details are kind of technical, but the basic steps are: 1) keep track of past game states (a save state), 2) restore a past game state when an input is received (reload a save state), and 3) resimulate the frames since then but with the new input accounted for.
...All in the span of 1/60th of a second. You're basically adding time travel into your game, and it's gotta run FAST.

Not only that, but you need to rethink your game's logic to account for teleporting. Your code can't depend on things happening in order! Prepare to refactor and bugfix like never before.
And there are design considerations. The teleporting effect is most noticeable on actions with instant startup, so adding some startup time to an action (e.g. squatting down before a jump) can help mask it.
Similarly, introducing input delay on purpose can help mask teleports. When the Slippi team reworked Super Smash Bros. Melee to run on PC with rollback, they managed to get it running faster than on native GameCube hardware - so they could introduce some input delay without affecting players' muscle memory.
Adding rollback to a game is like adding a drive-thru to a restaurant: you need to rethink how everything works in order to enable an entirely different mode of operation.
(Caveat: unlike drive-thrus, rollback netcode isn't reflective of a broken transportation system that isolates us from our communities and contributes to global warming)

In spite of these challenges, rollback is the modern gold standard for fighting games.
It provides a unique combination of perfect cross-client sync, low input delay, and protection against fly hacks.
However, it's not a perfect fit for every game.
Games with persistent worlds or lots of players, such as battle royales or MMOs, will probably benefit more from a server-based model.
And for cooperative games or other low-stakes modes, simple state sharing is probably fine, since players are unlikely to cheat.
I hope you enjoyed this surface-level overview!
