How does ROLLBACK NETCODE work, and why is it so difficult to program? A whirlwind tour of different solutions #pixelart#gamedev
The setup: you have a video game with couch co-op (pictured) and want to add online multiplayer. Easy, right...?
(thread)
Well, it's not so simple. If you send each player's button presses over the internet (big arrows), there's some delay due to how far the signal must travel. So the inputs get out of sync between the 2 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.
OK, what if instead of sending INPUTS thru the net, we send STATES? E.g. instead of "I pressed the A button", send "My character is at position (x,y), has 5 coins, etc".
On the surface, it looks the same, since you're still out-of-sync due to delay...
...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.
PROBLEM: Each client is now TRUSTING the other client to send accurate state information. So if P2 hacks the game to make Luigi fly on his screen, P1 will trust it, and P2 will have an unfair advantage.
So that's kinda wack.
Here's another approach: what if P1 runs the game, and P2 just STREAMS it? So P2 sends controller inputs, and P1 sends video/audio data. E.g. Steam remote play
No out-of-sync issues here, but P2 has HUGE input lag. He presses A but Luigi hesitates to jump. NO GOOD
What if you (the game dev) create a server to mediate player interactions? In this example, players send inputs and the server sends states, acting as a middle-man to verify that a state is valid.
Like before, state-sharing guarantees eventual agreement (but with the same "I should have hit him!" weirdness)...
...and you can even PUNISH people for hacking the game! Both players can safely trust the server to give accurate info.
Unfortunately, servers are too expensive for starving indie devs (e.g. Nintendo), so let's explore other options.
If you're making a fighting game, you don't want ANYTHING to be different across the 2 screens. Timing matters!
SO let's sync everything up by DELAYING the local input to match the network input. On P1's screen, Mario hesitates to jump.
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 / techniques needs to CHANGE in online vs local, or w/ connection speed.
On the plus side, notice that we're sending INPUTS back and forth rather than STATES - so cheating doesn't work. Luigi can't fly, since P1 just receives the A presses.
Some games will detect cheating by comparing player coordinates (but they can't tell WHO is cheating).
ROLLBACK NETCODE sends inputs 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.
This gif has bigger input delay. Notice on P1's screen, Luigi "skips ahead" to the peak of his jump: "teleporting" effect.
It's like missing your cue in a recital and skipping to the middle of the song (rather than starting from the beginning), to get in sync with everyone else.
...In practice, there's a LOT that needs to happen to make this work:
- Keep track of past game states
- Rewind time
- Resimulate those frames with the newly received input in mind
...all in the span of 1/60th of a second. You're basically programming time travel in your game.
I ran out of my fancy animations so here are some text-only posts :^)
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.
Another fun analogy: Rollback netcode is like Back to the Future.
BttF: Time travel back and ask "what would have happened if Marty's parents never met?"
Rollback: Time travel back and ask "what would have happened if P2 pressed jump 5 frames ago?"
Hope you enjoyed, share if you found it helpful!
*Technically P1 shouldn't see Luigi flying in this case, since P2 is only sending INPUTS. The specifics of how this works depend a lot on the type of server it is.
For example, you could have a server model where the players send STATES instead.
DISCLAIMER: I have never programmed netcode for a video game. Only offline stuff :^)
I don't expect there to be any major errors (except for one on the last Server gif; see replies there) but I apologize if there are any!
...I forgot to really cover this, but the reason rollback is great is because it combines:
1) No (or very little) input delay 2) Perfect in-sync 3) Impossible to cheat (no trusted state data)
So it's the gold standard for fighting games. All of the cool kids are doing it.
*the main difference is that rollback doesn't contribute to pollution, distance us from the people in our communities, and cause traffic jams :)
The "or very little" input delay is because a game can optionally ADD some input delay artificially. This reduces the "teleporting effect", so it might be worth.
Melee (on slippi) runs FASTER than gamecube by default, so it can afford to add delay and still feel silky smooth!
...Of course, when I say "impossible to cheat," I mean things like fly hacks. You can still have hacks like x ray vision or automatic button mashing.
In reality there's a lot that goes into a simple feature like this. Any new menu/UX requires a design process to make it a reality, but beyond that this feature also has some challenges attached to it.
First off, ANY menu you design for your game needs to go through the same design process to make sure it's very intuitive, polished, visually appealing, and bug-free.
This is rarely enough to kill a whole feature on its own. But it's a consideration in budget/planning.
It's not just "add some buttons and make them do stuff" - you have to ensure that the buttons feel good to use, the navigation makes sense, etc.
I downloaded the update and I think this menu even has new sfx? And the menu animations are also well-done.
How do you design a 2D GAME CAMERA that properly frames the action? A whirlwind tour of different solutions, animated! #pixelart#gamedev
The setup: you've made your platform game's player character and need to make the camera follow them. Easy, right...?
...Well, there's more to it than that. If you just lock the center of the camera to the center of the character, it won't give the player a very good view.
In fact, nearly half of the screen real estate is now dedicated to showing the ground texture... not helpful!
Easy fix: move the camera up a little bit! Now the player can see all of the blocks above, at least. But our work isn't done yet.
For one thing, the camera shows the menacing out-of-bounds void when the player walks near the edge of the map.