For example, another player stuns or slows down you, on the server, you will be slowed down or stunned
There is a delay there, from when the player initiates the stun until it reaches the server. For the player initiating the stun, it does not happen right away. If we do not deal with that lag, it will bite us later.
Let us follow the general approach: Send message to the server, and initiate animation (not a telegraphing animation, this is at the stage where there is not cancellation), and wait for server response.
Thus, when the player initiates the stun, it will play an animation, which has some duration. We, hopefully get the response from the server just when the animation ends. How much time must pass in the server so that the client receives the response form the server when the animation ends? That is animation duration minus round trip time for that player.
Thus, ClientA
:
- Send message to
Server
- Initiate animation (duration =
D
)
- Wait for server response ("stun happens")
Server:
- Receives message from the
CliantA
- Wait
D - ClientA.RTT
- Apply stun
- Send message to
ClientA
("stun happens")
Notes:
- Do not take Wait here as sleeping. It is more like "continue this process after this much time has elapsed", or "remember to do the rest of the steps after this much time has passed".
- By apply stun means that from that moment on, the server will take the stun into consideration in the simulation
but you will not know it before the packet arrives, since you are predicting the next state
Right, we must deal with the other player. The issue is that it can't predict being stun. If only the server could tell the player before the stun should happen… Wait, we can, because we dealt with the entry lag!
Server:
- Receives message from the
ClientA
- Send message to
ClientB
("you will be stun in X
")
- Wait
D - ClientA.RTT
- Apply stun
- Send message to
ClientA
("stun happens")
Hmm… So we need this feature where the server tells the client something will happen ahead of time (so that the client can take into account on its prediction).
If we can tell the client something will happen in the future, we can get rid of the wait on the server. Also how much time is X
? We can try to compute something like D - ClientA.RTT/2 - ClientB.RTT/2
, However, better talk in frames:
Server:
- Receives message from the
ClientA
Target_Frame = Current_Frame + (D - ClientA.RTT) / Frame_Duration
- Send message to
ClientB
("stunt will happen at Target_Frame
")
- Send message to
ClientA
("stunt will happen at Target_Frame
")
- Wait until Target_Frame
- Apply stun
And there you go. If all clients know on what frame they are, this works, they can predict the stun.
but you will not know it before the packet arrives, since you are predicting the next state, it will teleport you back because your speed was changed to 0 or lower (in case of slow), it will immediately turn you back (teleport).
This should not happen anymore. Because the client was able to predict the stun, because the server told it about it before hand. However…
You are still going to need interpolation. In some situations D - ClientA.RTT
will be negative. And that just does not work. In others ClientB
is too far behind.
You can, of course, tweak the animation so that D of reasonable length (keeping in mind that making it longer can be in detriment of user experience). But you can't control the round trip time. If it is long enough then interpolation is the way.