Multiplayer in fast games (Part IV: Headshot! Traveling in time)
- Transfer
- Parts I, II (single player with authoritarian server)
- Part III (The Appearance of the Enemy)
- Part IV (Headshot!)
How to hang a perfect headshot if you have ping 2 seconds? You will learn in this article.
Current multiplayer algorithm
- The server receives commands from clients and their sending times
- Server updates the state of the world
- The server sends its status to all clients at some frequency
- The client sends commands and locally reproduces their result
- The client receives updated world conditions and:
- Applies state from server
- Reapplies all its commands that the server did not have time to apply.
- Interpolates previous states of other players
- From a player’s point of view, there are two serious consequences:
- The player sees himself in the present.
- The player sees others in the past .
This usually works fine, but it becomes a big problem for events that need high spatio-temporal accuracy. For example, if you want to smash the head of the enemy !
Lag compensation
So you took aim with your sniper rifle directly to the opponent’s head. You exhaled calmly pulled the trigger. You are confident in your abilities, you cannot miss.
But you missed!
Why did this happen? How did this happen?
The fact is that in the architecture that we built, you aim at a place where the enemy’s head was 100 ms before the shot, not at the time you shot!
It's like being a sniper in a world where the speed of light is insane, just insignificantly small. You aim at your opponent, but by the time the light reaches you, he has long been gone from his old position.
Thank God, there is a fairly simple solution to this problem, which is also acceptable for other players most of the time (with one exception, which will be discussed later).
Here's how it works:
- When you shoot, the client sends a server shot event containing the server state time that was displayed at the time of the shot. And the exact direction of your weapon.
- This is the KEY moment. Since the server still sends its state every frame to clients, it can restore any moment from the past. In particular, he can restore the world exactly as the client saw him at the time of the shot.
- Thus, the server leaves the arrow in the position in which it is located; and the rest of the world changes to the state that the client displayed at the time of the shot, i.e. returns back in time .
- The server processes the shot and receives its result.
- The server returns the whole world to the current state of time.
- The server applies the result of the shot and sends updates to clients as usual.
And everyone is happy!
The server is happy because it is a server. He is always happy, because he is always right.
The shooter is happy because he aimed at the enemy’s head and smashed it with one accurate shot.
The dead is the only one who may be unhappy. If he stood still at the time of the shot, he himself was to blame. If he ran, then you are a good shooter.
But what if he ran across the danger zone, and a split second later he was shot dead when he thought he was safe? He will be upset.
This can happen. This is the compromise we are forced to make. Since the shooter shot him in the past, a player can be shot after he has already hidden behind a corner.
This sounds dishonest, but we will remember that from the point of view of the shooter, this player ran across the square as much time as from the point of view of the player. The only difference is the delay.
It would be much worse if the exact shot did not work!
Bring to the point of absurdity
It is important to note that this method works even with giant ping.
Attention, the trick is done by professionals! Do not perform this trick on a production server! Teams with a prescription of two seconds do not need to be performed in real life.
Conclusion
Such a thing as multiplayer is difficult to do correctly, but if you are armed with an understanding of the concepts described, there is nothing crazy complicated to implement.
Further reading (eng.):
Gaffer On Games
Valve's latency compensation methods
From a translator
This concludes a series of articles by Gabriel Gambetta .
But I do not say goodbye to you. I’m still going to write an article on how to build the serialization of the game world, and in general you never know where the study of such an interesting topic as multiplayer will lead you!
UPD
krimtsev asked a very reasonable question.
FPS and PING understand how they affect this, but what about TICKRATE?
I answer. Bogotoff and I allowed ourselves to move away from the described algorithm, since it seemed inconvenient for us to play at a server refresh rate of 10 times per second.
Since we use interpolation on the client to display the positions of enemies, it would not be entirely correct to apply the specific state of the server, which the client allegedly rendered, because in fact the player was shooting at an enemy who was between some two states.
Since we are applying the lag compensation mechanism, it can be used to find two states of the world between which a shot has occurred and to interpolate them.
Thus, you can adequately shoot even with a single server update per second:
Although the game at this server frequency, of course, looks awful. Do not do so. And generally keep the FPS as high as possible. The higher the sampling frequency of the game world, the more high-quality gaming experience the player will have. Although my personal IMHO that is above 60 does not make sense anymore.