Multiplayer game movement synchronization

后端 未结 1 1903
你的背包
你的背包 2021-01-31 06:23

I\'m working on a multiplayer game and i\'m having problem with synchronizing players.

When a player presses one of the move keys (W,A,S,D) then the client sends a packe

相关标签:
1条回答
  • 2021-01-31 07:07

    This is a very complex task you are working on and something I've done as part of a pet project ;)

    You're working on a client-server architecture game so the server is final authority on game logic and decisions. They way you are currently handling rendering will make sudden changes in velocity and direction apparent due to latency (as you have noticed!)

    The trick is to buffer movement information of remote players so you always render player with a slight delay. I kept things primitive in my project and used only positional data, not acceleration or velocity. Example, when player A moves on his machine a command is not instantly sent to receive acknowledgement, he moves and on the next tick of my networking send loop (10 ticks per second) his position is fired to the server who updates all clients in the vicinity with this new position. These clients have a buffer for each "remote" player which stores each position for a time (100 milliseconds) before rendering the update. In this way the client is rendered with a slight delay but I can interpolate (smooth the transition of the sprite/model) between each positional co-ordinate to achieve smooth motion with the illusion of velocity and acceleration.

    A BASIC interpolation function for client code. This system only queued two updates for each remote player at most, where index 0 in the update array was the older of two. So index 0 might be the remote player position 0ms and index 1 is the remote player position at 100ms.

    interpolate: function() {
      var timeDifference = new Date().getTime() - this.serverUpdates[1].time;
      // Percentage of time passed since update was received (I use 100ms gaps)
      var interPercent = (timeDifference) / 100;
    
      // Latest updates (index 1 is the newest state)
      var s1 = this.serverUpdates[0],
        s2 = this.serverUpdates[1];
    
      // Need to lerp between values provided in latest update and older one
      var p = (new Vector3(s2.position)).subtract(new Vector3(s1.position));
      p = p.timesScalar(interPercent);
    
      // New position is the older lerped toward newer position where lerp 
      //percentage is the time passed 
      this.position = new Vector3(s1.position).add(p);
    
      // Now update rotation in a smooth manner
      var rotationDifference = (s2.rotation - s1.rotation);
      if (rotationDifference && rotationDifference != 0) {
        this.rotation = s1.rotation + (rotationDifference * interPercent);
      }
    },
    

    In that code I was receiving updates that were approx 100ms apart, so at time 0 position is s1 and time 100ms s2 is the position. So if 50ms have passed since we received s2 then the entity is 50% between the two positions. This was fine for my need but may not work out in other types of games or might need tweaking.

    These resources are an excellent start to explain networked games and dealing with latency, you'll be amazed at the difference implementing interpolation and extrapolation will have on your game smoothness in remote clients.

    http://gafferongames.com/networking-for-game-programmers/what-every-programmer-needs-to-know-about-game-networking/

    https://developer.valvesoftware.com/wiki/Latency_Compensating_Methods_in_Client/Server_In-game_Protocol_Design_and_Optimization <- REALLY GOOD!

    https://developer.valvesoftware.com/wiki/Lag_compensation

    Good luck :)

    0 讨论(0)
提交回复
热议问题