Search Unity

LLAPI - Player movement

Discussion in 'Multiplayer' started by Hoshiqua, May 15, 2017.

  1. Hoshiqua

    Hoshiqua

    Joined:
    Jul 22, 2016
    Posts:
    77
    Hey !

    So I am still working along with a few friends of mine on that multiplayer game project. For now we managed to advance quite a bit - we got a lot of the major systems going, including connexion and matchmaking. However, this being the first time I do networking in 5 years of tinkering, I ran into many problems with.. latency.

    What I'm currently working on are the movements of players, and more generaly entities, which includes many other things than players, mainly the little AI soldiers players will be able to summon. But I digress.

    And of course I encountered problems with my system. It "works" but it's very unsmooth, even with some extrapolation and interpolation going. So here's how I'm basically doing it :

    Every entity on the server and the client has a "movement" vector associated with it. As its name suggests it is applied to the entity's position on the server every frame. When that vector changes, it is sent to the client along with entity's ID so the client knows which one to apply the new movement vector to. The client also applies the movement vector to entities locally, except for a few ones, namely the one controlled by the player (because extrapolation needs to be done, so for example instead of waiting for the server to confirm the player's entity movement vector changed after the player pressed a key, it starts moving the gameobject at the same time as it sends the "please change my movement vector" message to the server).

    As for rotation, every player entity sends its current rotation to the server every 0.25 seconds, which in turn sends it to all the other clients.

    On top of all this, every 2 seconds the server sends a "big" message with the current positions of all entities, as to prevent too much desync because of latency.

    Now, I'm not sure it's the best way to go about it. My thinking at first was that it was a good system because the server sends a small message and only when an entity changes its movement vector, as in when it is actually needed. But it's very unsmooth : the server has problems tracking a player's movement if he turns a lot, which is to be expected with a 0.25s rotation update period, not counting the time it takes for the message to reach the server. Of course I tried to lower that period but with so many messages sent every second the server was dying..

    I still have time to completely refactor that system if needed, so I'm looking for someone with more experience to explain a better way to do this. It's going to be a game with reflexes and such, so it has to be smooth and quick, while at the same time needs to be able to handle a few players (2 for now) and many MANY more secondary AI entities.

    I thank you in advance for your help !
     
  2. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    4hz is a very, very slow tick rate even for a MMO. Our game runs at tick rate of 20hz when server is full. 40hz if half full

    You should not force your entities to a position every 2 seconds, that will cause lag. Just extrapolate last known positon/rotation with your future calculated posiiton/rotation

    If you have too many AI enemies you need to come up with clever solutions for that, proximity, etc, etc
     
  3. Hoshiqua

    Hoshiqua

    Joined:
    Jul 22, 2016
    Posts:
    77
    Yes I think I'm doing what you're saying, I completely removed the movement vector stuff client side, replaced it with a system where entities constantly lerp towards the position the server gave them. Is that what you are suggesting ? As for the frequency, well, I'll try to put it down to 0.05, if 0.25 is such a slow rate. Thanks a lot for the quick response !
     
  4. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    I do not understand why you send each 2 second. If you sync at a fixed tick rate its not needed. Sure you will always have a latency desync but its not fixed in that manner. Its fixed by client side prediction (Extrapolation) on the clients and possibly lag compensation on the server (rewind state back as many milliseconds as the client latency).

    "a system where entities constantly lerp towards the position the server gave them"

    Sounds like you are doing it wrong, this will introduce lag and is not extrapolaton its interpolation, the opposite. You need to estimate the next future frame and lerp your current known server frame with this future frame. The most naive way is just to estimate by velocity. It can make fast moving objects move through stuff though
     
  5. Hoshiqua

    Hoshiqua

    Joined:
    Jul 22, 2016
    Posts:
    77
    Well, basically what I'm doing now is either I extrapolate (while in movement) and let the client side gameobject move and turn as he pleases, but once it stops it interpolates (lerps) to the position the server "thinks" he's at. It works pretty well so far :) Thanks for your help !
     
  6. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    Why do that? That should only happen if the server for authority reasons want to invalidate a client side movement.
     
  7. Hoshiqua

    Hoshiqua

    Joined:
    Jul 22, 2016
    Posts:
    77
    Well, I'm going for a full authority server because the game will be design for maximum competitiveness so we can't afford to have the slightest desync or cheating or whatever. But I'm not sure I understand - how do you keep the object any close to the location it is on server side ? Good extrapolation can do the trick sure but for small reasons like rotation update and plain lag you end up with quite a difference on each player's screen if you don't force every entity to be where the server thinks they are every so often. At least that's what I've observed.
     
  8. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    Well the code is good enough for this kind of interaction ;)



    I dont see how moving player back every other second helps in that regard. We authorize mostly important stuff like ownership taken/lost,Shots fired, and stuff like that. We also have some crude checking of impossible movements by player.
     
  9. Hoshiqua

    Hoshiqua

    Joined:
    Jul 22, 2016
    Posts:
    77
    So the server does not authorize each step.. does that mean movement server side is handled by the client giving it its current position and rotation every so often, with the server only checking for the distance travelled and such to prevent cheating ? Am I understanding this correctly ?
     
  10. Deleted User

    Deleted User

    Guest

    Hey Hoshiqua,
    I'm taking some guesswork with the following, as I am unsure of a few specifics on your setup.
    Number players, objects, network configuration etc...

    It sounds like you are already doing some testing and have seen that sending position data over every frame causes latency. Think of it like this.

    Say the client is sending to the server it's positional data every frame. Now the server is doing it's authoritative check and sending positional data back to the client every frame. But, the server is also sending each client or entity everyone else's positional data every frame. This is all compounded every entity or player that you add. So if your sending 60 messages a second with 1 client, you really sending 240 messages with only 2 clients, over 500 messages with 3 clients and so on.

    This is why you may already be seeing latency, I imagine if you tested with a high number of player/entities with your current system the server would eventually choke itself to a halt.

    I think that in the long run most client -> server positional data is correct. Every once in awhile there is a big enough spike in latency where things need to be corrected for the client but really no need to check for these every frame. More of a special case check. Even with cheating considered.

    I would not even worry about the cheating aspect for right now.
    First focus on getting everything running smooth with your _maxClients. This is not very hard to achieve just by thinking that most of the time the client and server data will be 1:1 correct, or correct enough and within a _tolerance value depending on your game play requirements/mechanics.

    You can think of the positional data as a buffer on the client and server. When you start just fill the buffers with empty values and as the game is played populate the buffers with new positional data based off of some measurement in time (something that is fast enough to achieve what you want, but not too fast to bog the server down). This part will take constant tuning and is more of an art than programming. Just remember, most of the time everything is already correct so don't waste the processing power.

    So the client and game objects are moving around and sending positional data (the buffer) every now and again.
    At the current time +1/2 roundtrip client ping the server is also moving the client and objects + other clients while it fills up it's own positional buffer.

    When the server gets a position update (the buffer contents) it runs a check against it's own positional buffer. If there is a mistake you seek the buffer to the last known correct position, set the client and server objects to that position or game state, and start overwriting the buffer as usual again from that position. Rinse and repeat.

    Easier to think of the buffers as a timeline. Time only moves forward so you don't need to check the whole buffer, as everything will be overwritten once you reach the end of the buffer. Instead check a portion of the buffer and only read more if there was a positional mismatch. Again, you only need to check a portion of the buffer because most of the time client and server are 1:1. And since the buffer is being filled and checked (at a fast enough rate to appear smooth) and time only moves forward, when a mismatch does occur the fix goes unseen.
     
    Last edited by a moderator: May 16, 2017
  11. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    Yeah, 20 or 40 times per second depending on distance to object or number of people playing we send the client pos and rot to the server. It validates the cordinates and send them to the other clients. Between these fixed updates the client guesses the future frame from server and interpolate current known frame with this future frame. Aka client side prediction or extrapolation. We do some naive raycasting too to make sure objects does not clip like a grenade being thrown.
     
  12. Hoshiqua

    Hoshiqua

    Joined:
    Jul 22, 2016
    Posts:
    77
    Thanks a lot for the help, now it's all smooth and good. Did as you suggested : the client tells the server its new position and then the server either 'lets through' or adjusts it if it thinks it's huge lag / cheating. However, I've ran into another problem : I have tried "stress testing" the server but the problem is that the server is actually a central server to which all the players connect. Now I understand why a single lousy computer couldn't act as a high performance server but it started being super laggy even before like 80 messages / second. Now, I'm not sure if it is client side or server side, I suspect it's a bit of both : the matchmaking had very noticeable "latency" even when both the clients were on the same computer as the server (meaning lag should be 0 right ?), and at the same time I can see why the clients would adjust the player's position constantly because not enough updates from the server coming through, which gives this impression of "lag".

    So, what can I do ? I can't really lower the amount of messages sent that much otherwise movement would look a bit wierd. Are there any other solutions to optimize the server ?
     
  13. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    Are you doing unreliable UDP? Its no idea doing reliable UDP for something like position and rotation sync. If you miss a message its still too late todo anything about it anyway. 80hz is a bit tad much for variable sync. With pretty basic client side prediction you should get ok result with 20hz or similar.
     
  14. Hoshiqua

    Hoshiqua

    Joined:
    Jul 22, 2016
    Posts:
    77
    Does using unreliable make such a difference in speed ? I'm using it already, yes, but I'm not sure what the benefits over reliable are. I just know it's somehow better to use that for information that isn't critical. And yes, it's about 20hz per individual match ongoing on the master server. I might want to write some code to allow for "match servers" to exist on other machines than the master server.
     
  15. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    Yes reliable UDP is basicly reinventing TCP over UDP, its potentialy much slower than unreliable