What are Server-authoritative Realtime Games?
Have you ever wondered how games like VALORANT, Diablo 3, or Dota 2 seem to keep everyone’s characters and actions in-sync, even if the players have differing pings? Behind this well-maintained façade is actually a lot of highly-technical trickery to make things work.
The abovementioned games are from different genres, but share a common trait of being server-authoritative — that is, all actions by players are simulated and validated by the server. Found a way to move way faster than allowed in the game (at least on your client)? Chances are, the game server will not agree on your position and snap you right back where it thinks you should be. The server’s version of the state of the game is the absolute source of truth, and such a model is inherently more secure.
So how is this achieved?
Let’s take a generic FPS game as an example. If I start to move my character, it takes a bit of time before the server gets the data for that action. The server then takes a bit more time to process the action and update the state of things, before broadcasting that “Player A moved forward” to all other players in the match. By the time the other players receive this information, wouldn’t it already be stale?
This is true! What you see on your screen when playing such a game is actually not what the server is seeing at the same point in time. In these games, game time is measured in discrete increments called ticks. What you’re looking at is at least a few ticks behind what the server knows.
How does it still feel “smooth” then? There are 2 factors at play here. The first is that the server updates really quickly. VALORANT game servers, for example, have a tick rate of 128Hz, which means it updates 128 times a second. Consequently, any differences in the game state between 2 consecutive ticks will be very small, and imperceptible to most people. If your latency to the server is high, however, these deviations will become more obvious.
This is where the second trump card comes into play: Client-side prediction. By knowing the past few ticks’ worth of game state and the players’ inputs, the game client can make predictions about where the game entities will be at and behave accordingly. As new data from the server is received, corrections will be made if the predictions are wrong.
The umbrella term for how these things are resolved in a networked game is called Netcode. Here’s a really good explainer by some of the people who worked on it for Overwatch: https://www.youtube.com/watch?v=vTH2ZPgYujQ. Note that “Favor the Shooter” is something specific to them, and not universal when talking about netcode.
So how can I do something similar in my game?
The games I mentioned at the start all have one thing in common: They were created by companies with significant resources. They have highly experienced teams working to make the gameplay as smooth as possible behind the curtain. That’s not something that every game developer has access to.
Fortunately, if you’re developing your game on Unity, there are solutions that are publicly available. Here are a few:
These frameworks handle a lot of the heavy lifting needed to accomplish the task, but you’re still going to need a lot of engineering work to get it working as you want it to. Get ready — we’re going into the weeds now. You’ll need a bit of technical understanding to fully appreciate the scope of things I’ll be explaining.
So what’s the catch?
Even with these tools, it will still take a lot of blood, sweat, and tears to get any of them working well enough to provide the best experience for the player.
It takes a lot of processing power to keep a server-authoritative game server running at full speed. The VALORANT game servers, with their 128Hz tick rate, only have around 7.8 milliseconds to do everything for each tick.
Here’s a non-exhaustive list:
- Update entity (including player character) positions
- Do collision checks
- Process player input
- Broadcast data to players
That’s very little processing time to do a lot! Achieving this will require a razor-sharp focus on performance and optimization. Most likely, you’ll not want your server updating faster than 60Hz so you have more breathing room, and also keep the server hardware requirements to a manageable level, lest they drive up the cost of your servers.
In addition, remember when I was extolling the benefits of prediction? You’ll actually have to implement how the prediction is handled in non-standard cases — which usually means anything beyond character movement. You’ll also have to be selective about what you want to predict in order to reduce the amount of processing needed, and indirectly lower your server costs.
Optimisation will be the name of the game during development, and some smart choices will have to be made in order to achieve performance targets. For example, in a game like Diablo 3, do you really need to spawn every monster in the map immediately, even if they aren’t near any players? Probably not. It would just add more entities that don’t need to be updated since they’re so far away from any player activity. Instead, it would be better to spawn them as the player moves around, especially since the player will likely be removing some monsters along the way.
So what now?
While it may seem daunting, server-authoritative games can offer the best multiplayer experience for players when done well. Your resources (in all senses of the word) will be limited, so during development, decide what’s important to predict for the best player experience, and focus on achieving that. I hope that this article has given you a good introduction to server-authoritative games and the challenges in making one. Disney Melee Mania was our first server-authoritative real-time game. You can read more about some of our engineering adventures in trying to bring the game to fruition:
In a future article, we’ll cover more specific things about how we used Unity Netcode for Disney Melee Mania.
And if you’re thinking of making one — All the best in your journey in this world of server-authoritative games!