Something that makes me wonder about game state prediction

CrushaKCrushaK Join Date: 2012-11-05 Member: 167195Members, NS2 Playtester
I know that NS2 uses some clientside prediction, but there are a few things that confuse me:

For instance why any kind of player interaction on the server just stops the moment that I lose the connection as client, even if it's just for a moment or two.
An example would be the attack command. If I start chewing on an RT, keep holding the Fire key down and suffer from a short disconnect during that, the RT will happily continue to lose HP on my client version of the game. But it actually does not on the server.
The server seems to require a constant connection to the client and it also doesn't update my client about it's false clientside HP value of that extractor (resulting in situations where I need to get in 5-10 additional bites even though the RT has already 0 HP left on my client).

I would actually have assumed that the server predicts the client's actions based on their last input. So on the client I press the key for firing, that causes the server to get notified: ClientA.StartFire(), maybe sets some flag and then keeps executing whatever action is associated to firing at the fixed FireRate interval until I send the StopFire() command by releasing that key.

Similar instance when building stuff as marine: I often tend to lose the connection during that and thus there are moments where I just stop building something even though the server could easily simulate my action until I tell him that I stopped doing that.

Those are two instances where some server-side prediction with a Start/Stop system would make packetloss much more forgiving in this game since those RT attack or structure build seconds that I was missing out could often make a crucial difference in the game, for instance if the thing I am building is a lone PG on the other side of the map and aliens are approaching.



Another thing is simulating the player's position based on his last inputs on the server instead of stopping everything as soon as you lose connection. Currently when I am using the connection as Lerk for just a second during a fight, that basically guarantees me to be dead as soon as I am back. Why? Because apparently the game freezes any player in position as soon as he loses the connection. (According to what my confused killers always tell me.) I am some ultra fast flying alien bird, I probably have a Velocity vector and an Acceleration vector associated with me, so why does it stop me dead in my tracks in midair, ignoring any physics that might take place, instead of just continuing to update my position based on my Velocity while I am disconnected? If that Lerk would just keep flying, it would make it so much harder for marines to get a free kill in that moment.



And last but not least some weird instance of what looks like missing clientside prediction:
When I lose the connection as client (aka red plug), this also seem to stop all dynamic entities in the map. I see that it makes sense for stuff that actually collides like those big pods in Smelting, but I don't see why some purely cosmetic thing like rotating fans that are just there for some nice lighting effects need to be synced up to the server and completely cease to rotate in the very moment that I lose the connection. Doesn't that mean that all those fans are unnecessarily using up bandwidth when they could be predicted on the client just fine?

Comments

  • Kouji_SanKouji_San Sr. Hινε Uρкεερεг - EUPT Deputy The Netherlands Join Date: 2003-05-13 Member: 16271Members, NS2 Playtester, Squad Five Blue
    The way you're describing it is highly susceptible to exploits, A better way would be to check for packet loss and update the client to the server state, as in resetting you to the state you were on before you lost connection. This would also be called rubber banding, which is more visible during movement. Which means when you move and lose connection for a short period, you get reset to your previously known location.

    The server should always be in full control and not have to rely on predicted client data or client data in general.

    The game also shouldn't aid people who have connection issues, it would be better to fix your connection issues instead. Sounds to me like a faulty or bad router if you're having these constant connection jitters...
  • CrushaKCrushaK Join Date: 2012-11-05 Member: 167195Members, NS2 Playtester
    edited March 2013
    I think you are misunderstanding me. I am not suggesting that the server takes a client's predicted data for given - the server is till the man. I am suggesting that the server himself keeps processing (rather than predicting) a player's ongoing action based on the last received input from the client until the client tells him that he is no longer doing that thing. Instead of basically only doing stuff for the current tick if the player told the server in that tick what he's doing.
    (Please take note that I have no idea how the current system actually works. I am just making assumptions based on how it currently behaves during packetloss conditions.)

    So if a player is moving forward and loses the connection while doing that, he will keep moving forward on the server's version of the game. Since the player will likely still be pressing his forward movement key before he even notices the connection loss, the server's version of the game and the client's predicted version will still be pretty much the same. The client would only notice it for sudden direction changes during the packetloss phase.

    The Start/Stop system for stuff like attacking wouldn't really be exploitable either because everything still happens in the rules of the server's game. Just that instead of having the player send the server an "I want to attack now" command on every tick that he keeps the button pressed and the server checking if the player can actually attack, the server now assumes that the player keeps the button pressed until the player tells him that he is no longer doing so and then the server keeps performing his checks on whether the player can actually attack as usual.


    That rubberbanding is btw already occurring for the client under packetloss circumstances. You get pretty harshly reset to the server's version of the game state upon any red or even yellow plug. Just that stuff like structure HP seems to take a lot longer to be updated on the client then.
    The methods described above are for instance how it's done in the Unreal Engine for ages. There is even some grace included for the different movement predictions between client and server: if the difference between the authoritative player's predicted location and the server's predicted location is small enough, the server will smoothly (so it looks like intentional movement in that direction to other players) correct the serverside location of that player to match the predicted location of it's controlling player for the sake of not disturbing that player with an abrupt change to what the server deems the correct position. Only if the difference in position is too big will the server actually reset the client to what he thinks is the correct position.

    And accounting for potential issues from ping and packetloss is actually well within the stuff that developers consider. In the Unreal Engine can you for instance even simulate a specific ping and percentage of lost packages in order to test how your game behaves then and if problems might occur.

    As for my packetloss, it's related to me having to use WLAN and there is no real way around, hence why I appreciate games that take at least a little care of it. Unfortunately did Valve for instance start to not pay that much attention to it anymore and seem to be whoring around with their network traffic in TF2 that the formerly perfectly playable game now results in at least one major connection issue per match for me, probably due to all the additional data that I need to be made aware of for player's fancy loadouts and bling bling. I rarely play TF2 these days because there is only so much "missing a perfect backstab as Spy due to sudden packetloss" that you can take.
  • |strofix||strofix| Join Date: 2012-11-01 Member: 165453Members
    Stop/start is stateful, which UDP struggles with.
  • CrushaKCrushaK Join Date: 2012-11-05 Member: 167195Members, NS2 Playtester
    edited March 2013
    That's the difference between reliable and unreliable UDP.

    In the Unreal Engine do you mark function calls over network either as reliable or unreliable. The unreliable one sends the function call once with UDP and doesn't care if it's lost. The reliable one will keep sending the package until the client acknowledges that he received it.
  • |strofix||strofix| Join Date: 2012-11-01 Member: 165453Members
    CrushaK wrote: »
    That's the difference between reliable and unreliable UDP.

    In the Unreal Engine do you mark function calls over network either as reliable or unreliable. The unreliable one sends the function call once with UDP and doesn't care if it's lost. The reliable one will keep sending the package until the client acknowledges that he received it.

    Such a system would obviously be fine for something like logging into the comm chair or hive, since the action occurs rarely and is in itself stateful. However, you couldn't possible use that for something as ubiquitous as attacking.

  • CrushaKCrushaK Join Date: 2012-11-05 Member: 167195Members, NS2 Playtester
    |strofix| wrote: »
    CrushaK wrote: »
    That's the difference between reliable and unreliable UDP.

    In the Unreal Engine do you mark function calls over network either as reliable or unreliable. The unreliable one sends the function call once with UDP and doesn't care if it's lost. The reliable one will keep sending the package until the client acknowledges that he received it.

    Such a system would obviously be fine for something like logging into the comm chair or hive, since the action occurs rarely and is in itself stateful. However, you couldn't possible use that for something as ubiquitous as attacking.

    Do you really think there is a big difference between "sending StartAttack package x times until it reaches server + sending StopAttack package y times until it reaches server" and "sending IAmAttacking package xyz times for the duration that I am firing"? Or at least one that makes the latter a better choice?

  • |strofix||strofix| Join Date: 2012-11-01 Member: 165453Members
    edited March 2013
    CrushaK wrote: »
    |strofix| wrote: »
    CrushaK wrote: »
    That's the difference between reliable and unreliable UDP.

    In the Unreal Engine do you mark function calls over network either as reliable or unreliable. The unreliable one sends the function call once with UDP and doesn't care if it's lost. The reliable one will keep sending the package until the client acknowledges that he received it.

    Such a system would obviously be fine for something like logging into the comm chair or hive, since the action occurs rarely and is in itself stateful. However, you couldn't possible use that for something as ubiquitous as attacking.

    Do you really think there is a big difference between "sending StartAttack package x times until it reaches server + sending StopAttack package y times until it reaches server" and "sending IAmAttacking package xyz times for the duration that I am firing"? Or at least one that makes the latter a better choice?

    It all depends on how well you want the system to run.

    In an FPS, firing your weapon is a pretty important part of the game, so that message is going to have to be sent at every opportunity possible. You can't send it once and then assume it will make it, but wait another second before sending it again just in case. That would create a horribly jarring experience in game.

    The next problem is the "until it reaches the server". With UDP you just fire the packet and forget about it. Maybe it reaches its destination, maybe it doesn't. When you need to ensure that the information does reach the destination, things change a lot. Now not only do you have to constantly stream the information to the destination over and over again, but the destination has to acknowledge that it has received them. Then you might just have to acknowledge that the other end has acknowledged your first transmission. The REQ/ACK procedure for even the most simple of interactions can be a complete nightmare.

    In short, yes. Whenever you must ensure reliability in an inherently unreliable transfer system, things become very different.
  • xen32xen32 Join Date: 2012-10-18 Member: 162676Members, Reinforced - Supporter
    Looks like someone needs better ISP.
  • CrushaKCrushaK Join Date: 2012-11-05 Member: 167195Members, NS2 Playtester
    edited March 2013
    |strofix| wrote: »
    Then you might just have to acknowledge that the other end has acknowledged your first transmission. The REQ/ACK procedure for even the most simple of interactions can be a complete nightmare.

    The function call would get a unique time stamp/ID associated with it. The receiving end would then refer in the acknowledgment to that specific ID and would also sort any additional incoming calls out based on it (aka "I already received this package, so I will ignore the function call in it but send another acknowledgement that will hopefully stop any additional packages with that ID from being sent, since my last one might not have made it"). The sender would then also check if incoming acknowledgments refer to the specific ID to sort out the multiple ones that are being sent.

    Overall the benefit of the system increases the longer the period between the start and stop is, since that determines what bandwidth got saved compared to naive UDP.

    |strofix| wrote: »
    In an FPS, firing your weapon is a pretty important part of the game, so that message is going to have to be sent at every opportunity possible. You can't send it once and then assume it will make it, but wait another second before sending it again just in case. That would create a horribly jarring experience in game.

    You are exaggerating the "one second" here. The packages are sent at the server tick rate, which is usually 30 times per second for a fluid game experience. The method has proven itself in fast shooters like the Unreal Tournament series and I don't remember any "horribly jarring experience" in it.

  • ogzogz Join Date: 2002-11-24 Member: 9765Members
    probably more important things to look into than whether or not to send some .startattacking or .startbuilding commands when someone DCs in the middle of a game.
Sign In or Register to comment.