Intro to network latency
Distance between server and clients, packet hops, a server’s tick and update rate, and a plethora of other issues contribute to multiplayer lag – here’s how to address it.
Online games have issues that single-player or LAN-only games don’t have to worry about, such as jitter, round-trip time (RTT), or packet loss.
Any kind of delay between sending, receiving, and queuing information between clients and servers can cause an issue for gameplay. For a full list of definitions and problems, check out this guide here.
To successfully address latency problems, you need to consider the priority and relationship between the following elements:
1. Security
2. Reactivity
3. Accuracy and consistency
No solution is perfect, and every way to approach latency issues has strengths and weaknesses. The key is to find the way that works best for your game and this guide will help you understand how to make that decision.
Authority defines who has the right to make final gameplay decisions over objects in the client-server relationship. The authority model you select has implications for the network latency in your game.
There are two authority types in multiplayer games, and each has its own relationship with security, reactivity, and consistency:
- Server authority: More secure, less reactive, no sync issues.
- Client authority: Less secure, more reactive, possible sync issues.
Any code that exists on the client’s side can be tampered with and players can forge false network messages sent to the server.
If you want to know how this might end up looking in your game, consider the example of a game where you cannot kill imps from a certain distance.
If you specify in your client logic that you can't kill these imps more than 10 meters away, but the "kill imp" message is a server RPC that doesn’t check distance server-side, players can forge that network message to bypass your client side logic.
Unfortunately, some people will always try to mess with your game so you should always keep in mind you can never fully trust clients. For the sake of those poor imps and all others playing your game, your server needs logic to validate player actions coming from clients.
Authority models and latency
The authority model you select has implications for the network latency in your game. Let’s review the two authority types and their relationship with security, reactivity, and consistency.
A server authoritative game has all its final gameplay decisions executed by the server.
Security ✅
Critical data such as your character health or position can be server authoritative to ensure that cheaters can't mess with it. In that instance, the server will have the final say on that data's value.
Consistency ✅
An advantage of server authoritative games is your world's consistency. Since all gameplay decisions are made by the same node on the network (the server), you can be sure these decisions are made at the same time.
Reactivity 🚫
An issue with server authority is that you end up waiting for your server to tell you to update your world. However, stay tuned as there are patterns you can use to solve this issue while still remaining server authoritative.
In a client authoritative game, you still have a server that's used to share world state, but clients will own and impose their own reality.
Reactivity ✅
A client authoritative model can often be used when you trust your users or their devices, and it’s a useful model for reactivity. Since the client itself is making all the important gameplay decisions, it can display the result of user inputs as soon as they happen.
Consistency 🚫
Client authoritative games may run into sync issues. If you let your client make an authoritative decision using outdated information, you'll run into desyncs, overlapping physics objects, and other such issues.
Security 🚫
Client authority is a pretty dangerous door to leave open on your server, since any malicious player could forge messages to win the game.
Solving latency issues in server authoritative games
The best practice for multiplayer development is to adopt a server authoritative model for consistency and security. Let’s cover four key strategies to manage latency in these games.
When designing your feature, use server authority as the default and then identify which feature needs reactivity and doesn't have a big impact on security or world consistency.
User inputs are a good example. Since users already own their inputs (I own my key press, the server can't tell me "no you haven't pressed the W key”), user input data can easily be client driven.
In FPS games, your look direction can easily be client driven without much impact. The client will send to the server its look direction instead of mouse movements. Having a correction on where you look would feel weird and security for this has its own challenges.
Prediction can keep your game server authoritative while staying reactive. Your client simulates and runs gameplay code that anticipates your players’ trigger inputs instead of waiting a full RTT for action results.
This is where "reconciliation" comes into play – when errors occur in the prediction. The client keeps a history of the positions it predicted, and, being server authoritative, the client still receives positions coming from the server. The client will validate whether the positions it predicted in the past fit with the old positions coming from the server.
The client can then detect discrepancies and correct its position according to the server's authoritative position.
Note: This method is not fully supported by Netcode for GameObjects at this time.
There's multiple reasons for not having server authoritative gameplay code run both client side (with prediction) and server side. But how do you make sure the throw feels responsive and that your client doesn't have to wait for a full RTT before seeing anything react to their input?
A trick often used for lag hiding is to trigger a non gameplay impacting animation, sound, or VFX on player input immediately, but still wait for the server authoritative gameplay elements to drive the rest of the action.
If the server has a different state, the worst that happens client side is that you've played a quick but useless animation. It's easy to just let the animation finish or cancel it. This is referenced as action casting or action anticipation.
Server rewind is a security check on a client driven feature to make sure we stay server authoritative.
The client sends along with its input a message telling the server "I have hit my target at time t". The server when receiving this at time t+RTT/2 will rewind its simulation at time t-RTT, validate the shot and correct the world at the latest time (i.e. kill the target). This allows for the player to feel like the world is consistent while still remaining secure and server authoritative.
Note: The server rewind of the game's state is done all in the same frame and this is invisible to players. This is a server side check that allows validating a client telling you what to do.
Note: This method is not fully supported by Netcode for GameObjects at this time.
Building a multiplayer game is a challenging endeavor, but also an exciting one. Whether you’re building the next battle royale smash hit, or a cozy online co-op, understanding the nuances of latency and how to manage it is essential.
Check out our multiplayer documentation to get started with your next project today.