Jump to content

  • Log In with Google      Sign In   
  • Create Account

Client-Side Prediction & Packet Loss


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
41 replies to this topic

#1 Heg   Members   -  Reputation: 173

Like
0Likes
Like

Posted 19 September 2012 - 02:46 AM

Hey guys,

I am currently working on my online mode for my Bomberman Clone. I´ve implemented a UDP Layer so far that has some reliability functionality, such as package acknowledgements. I am now implementing the client-side prediction and got a few questions to that.

In all tutorials I´ve read so far, the only things that lets client-side prediction fail are unpredictable events, usually when another player interacts with your player. But what about packet loss? When I move to the right, I can predict the new position pretty easily, but when the command never reaches the server, the new position will be false. Maybe that wouldn´t be such a huge problem, but I´ve got real issues when thinking about planting bombs:

Planting bombs could normally be predicted, since the client knows the rules for planting bombs. You can´t plant bombs when you already planted all of your bombs on the field, or when there is already a bomb at that location. The letter can be a result of the influence of another player, i.e. when someone planted a bomb a tad before you did. This situation would result in the same visual output though, since a bomb is still at the predicted position.

When packets get lost around the bomb planting command, then the prediction would also fail. Maybe the position of the player needed to be corrected, so when he dropped the bomb he actually was at a different location. Another possibility could be that the bomb planted command never reaches the server. I could resend the command, but that would also result in a different bomb location.

Correcting this mistakes could lead to teleporting bombs, which in return could cause trapping yourself. That would be a horrible scenario, since you literally get killed by packet loss. Not predicting bombs on the other hand always results in a bit of unresponsiveness, which is also frustrating. What can I do? Help Posted Image

Edited by Heg, 19 September 2012 - 02:50 AM.


Sponsor:

#2 rnlf   Members   -  Reputation: 1121

Like
2Likes
Like

Posted 19 September 2012 - 03:03 AM

My personal approach here would be to just use TCP, timestamp every command and predict everything the way you do. Even with a retransmitted or slightly delayed command here and there, due to the timestamp you will be able to simulate the game "as if" the command reached the server in time. If state updates from the server reach the client to late, so that the prediction is wrong, well, even AAA titles have this problem (the famous shot around the corner lag problem for example). Guess it's unavoidable with today's networking technology.

my blog (German)


#3 Heg   Members   -  Reputation: 173

Like
1Likes
Like

Posted 19 September 2012 - 03:23 AM

Hi, thanks for your answer.

I don´t see why TCP would be a better option in this case. My UDP Protocol allows me to detect package loss and the order of my packages by using sequence numbers. This leaves me with the option to resend important data or just ignore less important packages, which were recieved either too late or not at all. What I have in mind here is movement data from other players. If those are missing, they don´t need to be resend, because the client doesn´t care about the old data.

#4 Ashaman73   Crossbones+   -  Reputation: 7454

Like
2Likes
Like

Posted 19 September 2012 - 03:38 AM

but when the command never reaches the server

You can use a hybrid solution. For player commands (relative seldom, low data volume) you can use TCP to take away the burden of self-implemented reliability and use your UDP stack for the rest.

But I'm not sure if a UDP stack is still necessary for smaller projects nowadays, so Heg has a point here.

#5 Inferiarum   Members   -  Reputation: 732

Like
0Likes
Like

Posted 19 September 2012 - 03:38 AM

you could also use the information from the prediction just to draw the player and wait for the server state packages to draw everything else.

#6 Heg   Members   -  Reputation: 173

Like
0Likes
Like

Posted 19 September 2012 - 03:50 AM

Hm, this tutorial highly stresses that UDP and TCP shouldn´t be used together, since both are using the IP Protocol and therefore are not independend from one another.

Since I already implemented the UDP functionality I could might aswell use it. I could just resend client input that didn´t go through, including a timestamp, so that the server can reproduce the input. That way the server would have to wait for missing input until it can process the client correctly. I think that wouldn´t be too big of a deal, but I am not sure yet.

What do you mean Inferarum? I think you suggest to just draw player positions and let everything else be approved by the server first. In my case that would result in drawing bombs as soon as the server confirms the position, which would result in a slight delay between pushing the button to plant a bomb and the appearence of the bomb. I fear that this would feel to unresponsive though. What do you guys think?

#7 Inferiarum   Members   -  Reputation: 732

Like
1Likes
Like

Posted 19 September 2012 - 04:11 AM

I guess most games have this delay for projectiles emitted by the player

#8 Ashaman73   Crossbones+   -  Reputation: 7454

Like
4Likes
Like

Posted 19 September 2012 - 04:58 AM

To be honest, it seems that you build a theoretical horrible scenario which is really unlikley to happen, this is just a game not a control program for the mars probe.

When the player places a bomb just display it as placement plan, that is, make it translucent and leave it in this state until you receive the ok from the server. The standard case will take a few ms, even with a packetloss, most players will not recognize the delay. And if an other player just placed a bomb on the same location just one single ms before, remove the translucent marker and play some sound to inform the player about the failed operation.

#9 Heg   Members   -  Reputation: 173

Like
0Likes
Like

Posted 19 September 2012 - 05:02 AM

To be honest, it seems that you build a theoretical horrible scenario which is really unlikley to happen, this is just a game not a control program for the mars probe.

When the player places a bomb just display it as placement plan, that is, make it translucent and leave it in this state until you receive the ok from the server. The standard case will take a few ms, even with a packetloss, most players will not recognize the delay. And if an other player just placed a bomb on the same location just one single ms before, remove the translucent marker and play some sound to inform the player about the failed operation.


lol :D

Yeah you are propably right. I am really creating the worst case scenario, but someone smarter than me once said "what can go wrong, will go wrong". I guess I follow the advice of you two and wait for the response of the server. I´ll test that with different connection speeds and see how it feels. If it feels too unresponsive, I will add some kind of indicator that the command has been registered by the machine.

#10 Ashaman73   Crossbones+   -  Reputation: 7454

Like
3Likes
Like

Posted 19 September 2012 - 05:13 AM

If it feels too unresponsive, I will add some kind of indicator that the command has been registered by the machine.

You still should send the commands on a reliable channel, your UDP stack fits in here. Just remember the last X send commands + sequence number and the server will send acknowledge messages about the last valid sequence number from time to time (the client can clean up the command queue up to this number). Although the server should send resend-requests when it detects a gap asap.

You can even re-send the same command (unique sequence number) multiple times, using the space left in a UDP for best use and on the server side it doesn't matter at all.

#11 Heg   Members   -  Reputation: 173

Like
0Likes
Like

Posted 19 September 2012 - 07:54 AM


If it feels too unresponsive, I will add some kind of indicator that the command has been registered by the machine.

You still should send the commands on a reliable channel, your UDP stack fits in here. Just remember the last X send commands + sequence number and the server will send acknowledge messages about the last valid sequence number from time to time (the client can clean up the command queue up to this number). Although the server should send resend-requests when it detects a gap asap.

You can even re-send the same command (unique sequence number) multiple times, using the space left in a UDP for best use and on the server side it doesn't matter at all.


I´ll keep that in mind. I´ll let you guys know how it turns out ;)

#12 0BZEN   Crossbones+   -  Reputation: 2016

Like
2Likes
Like

Posted 19 September 2012 - 04:29 PM

On problem with using TCP and UDP together is that UDP packets tend to be dropped if you start to saturate your bandwidth. If you are nowhere near, then sure. However I prefer a full UDP solution, as it makes things easier in the long run. In any case, you can re-engineer the lower layers if you want to move away from mixing both UDP and TCP.

Secondly TCP can fragment your communication. Say, you send 10 bytes message + 20 bytes message + 10 byte message. Then you may received that data in the form of 12 bytes + 12 bytes + 10 bytes + 6 bytes packets. So you will need some reconstruction at the receiving end. A custom reliable message system piggy-backed on UDP can stop that kind of fragmentation, but really, it's not a big deal to fix that problem.

Edited by papalazaru, 19 September 2012 - 04:30 PM.

Everything is better with Metal.


#13 Heg   Members   -  Reputation: 173

Like
0Likes
Like

Posted 19 September 2012 - 05:12 PM

On problem with using TCP and UDP together is that UDP packets tend to be dropped if you start to saturate your bandwidth. If you are nowhere near, then sure. However I prefer a full UDP solution, as it makes things easier in the long run. In any case, you can re-engineer the lower layers if you want to move away from mixing both UDP and TCP.

Secondly TCP can fragment your communication. Say, you send 10 bytes message + 20 bytes message + 10 byte message. Then you may received that data in the form of 12 bytes + 12 bytes + 10 bytes + 6 bytes packets. So you will need some reconstruction at the receiving end. A custom reliable message system piggy-backed on UDP can stop that kind of fragmentation, but really, it's not a big deal to fix that problem.


Yeah, I agree with you. I already programmed a low level UDP layer including an acknowledgement system and all that stuff. So I will definitly use UDP only. I had just some issues around client-side prediction and packet loss. On important game decisions, like planting or exploding bombs, I´ll just wait for a server message and see how that goes. One thing I have to accept is that my game won´t work well when the internet connection is bad. I think there is nothing you can do about that.

#14 0BZEN   Crossbones+   -  Reputation: 2016

Like
1Likes
Like

Posted 20 September 2012 - 03:56 AM

Most games use a varying amounts of smokes and mirrors to mask internet issues.

However, if the connection is bad, it's generally better to let the user suffer for it rather than the game. The game should function well under a minimum requirement of conditions, and anything below that, best forget about it, as long as it doesn't break the game itself.

Planting stuff, or things more akin to 'events' (requesting pick up, climbing into a vehicle, planting a bomb, ...) in time are generally better dealt with with a reliable, but latency-heavy system. That isn't so much of a problem generally, these are often hidden behind client-side animations started at the moment of the request and aknowledged or cancelled by the server response.

Everything is better with Metal.


#15 Heg   Members   -  Reputation: 173

Like
0Likes
Like

Posted 20 September 2012 - 04:02 AM

Hm, I could make my guys "bend over" or something in order to plant the bomb :-P A translucent bomb will most likely look odd!

#16 Heg   Members   -  Reputation: 173

Like
0Likes
Like

Posted 22 September 2012 - 04:33 AM

I´ve got one additional quick question:

Best practice is to send out game updates from the server and input from the client at a fixed rate, say every 100ms. When we define the "effective latency" as the time between issuing a command and the response from the server, this technique does increase the latency by quite a big deal, doesn´t it? For example:

Server: |----------|----------|----------|-----

Client: --|----------|----------|---------|----

The | are the sending points and the time between them is 100ms. If the player on the client issues a command right after input has been send to the server, it would take almost 200ms to get a response, even when the packages arrive instantly. The first X marks the input time, the second one the response from the server:

Server: |----------|----------|----------|-----

Client: --|-X--------|---------X|---------|----

This is noticeable even on a listening server. I fear, when there is actually traveling time needed between the server and the client, that this will have a too big impact. What are your thoughts on that? Is a 100ms interval simply too big?

Edited by Heg, 22 September 2012 - 04:35 AM.


#17 hplus0603   Moderators   -  Reputation: 5302

Like
1Likes
Like

Posted 22 September 2012 - 12:18 PM

this technique does increase the latency by quite a big deal, doesn´t it?


Yes, it does! This is why CS:S servers running at "tickrate 67" or "tickrate 100" are popular among the low-ping addicts.

On consoles, you typically can't get away with better than 20 times a second (every 50 ms) and many games do it less (every 67 or 100 ms.) Seems to work well for them anyway. The trick is to tune the display and gameplay to work well with whatever your chosen network parameters are.
enum Bool { True, False, FileNotFound };

#18 Heg   Members   -  Reputation: 173

Like
0Likes
Like

Posted 22 September 2012 - 12:28 PM

this technique does increase the latency by quite a big deal, doesn´t it?


Yes, it does! This is why CS:S servers running at "tickrate 67" or "tickrate 100" are popular among the low-ping addicts.

On consoles, you typically can't get away with better than 20 times a second (every 50 ms) and many games do it less (every 67 or 100 ms.) Seems to work well for them anyway. The trick is to tune the display and gameplay to work well with whatever your chosen network parameters are.


Okay, so I rely heavily on my client-side prediction, lag compensation and interpolation then. Maybe it´s even a good thing that lag even affects local games. That makes it waaay more easy to test and requires me to work really hard on the networking stuff, otherwise the game will suck for everyone, not just for the guys with slow internet speed.

Edited by Heg, 22 September 2012 - 12:30 PM.


#19 0BZEN   Crossbones+   -  Reputation: 2016

Like
1Likes
Like

Posted 22 September 2012 - 04:48 PM

Okay, so I rely heavily on my client-side prediction, lag compensation and interpolation then. Maybe it´s even a good thing that lag even affects local games. That makes it waaay more easy to test and requires me to work really hard on the networking stuff, otherwise the game will suck for everyone, not just for the guys with slow internet speed.


Yes, you can also generate arbitrary latency for testing how it affects your game.

Usually your game update is staggered. First, Receiving packets, then updating your game (server or client), and finally sending your commands / states at the end of the update. It's one easy way to manage your game loop without adding unnecessary latency.

You can have a virtual network layer that can queue sending and / or receiving packets, as well as simulating packet loss, duplication and out of order (all of which should be invisible outside your lower network layer) for testing purposes, or if you lack the resources for proper internet testing. Then you can use renderless client-bots / servers, or just basic loopback networking with one player, like in Quake3 and many other Unreal / ID / Source games).

Edited by papalazaru, 22 September 2012 - 04:49 PM.

Everything is better with Metal.


#20 Heg   Members   -  Reputation: 173

Like
0Likes
Like

Posted 24 September 2012 - 05:55 AM


Okay, so I rely heavily on my client-side prediction, lag compensation and interpolation then. Maybe it´s even a good thing that lag even affects local games. That makes it waaay more easy to test and requires me to work really hard on the networking stuff, otherwise the game will suck for everyone, not just for the guys with slow internet speed.


Yes, you can also generate arbitrary latency for testing how it affects your game.

Usually your game update is staggered. First, Receiving packets, then updating your game (server or client), and finally sending your commands / states at the end of the update. It's one easy way to manage your game loop without adding unnecessary latency.

You can have a virtual network layer that can queue sending and / or receiving packets, as well as simulating packet loss, duplication and out of order (all of which should be invisible outside your lower network layer) for testing purposes, or if you lack the resources for proper internet testing. Then you can use renderless client-bots / servers, or just basic loopback networking with one player, like in Quake3 and many other Unreal / ID / Source games).


Yeah, I already got a few testing functionality in my network layer, such as latency and packet loss. I am missing functions for duplication and out of order though. I´ll make sure to implement that.

While we are at it, how do you guys handle lost or out of order client input? I would say client input needs to be ordered, but that would also imply that you would have to wait for a resend of lost client packages, since it´s not ordered when you are missing one package.
Should I really wait for such packages, or should I just let the client input get lost? This would result in a correction of the movement on the client, since it predicted the movement wrong.

Current state of the game: Client-Side Prediction and Interpolation seems to work quite well in my current implementation, but I am not reacting to lost, duplicated and out of order packages yet. That´s my next step :-P

Edited by Heg, 24 September 2012 - 05:56 AM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS