Gamasutra: The Art & Business of Making Gamesspacer
View All     RSS
November 20, 2018
arrowPress Releases
  • Editor-In-Chief:
    Kris Graft
  • Editor:
    Alex Wawro
  • Contributors:
    Chris Kerr
    Alissa McAloon
    Emma Kidwell
    Bryant Francis
    Katherine Cross
  • Advertising:
    Libby Kruse






If you enjoy reading this site, you might also want to check out these UBM Tech sites:


 

UNET Unity 5 Networking Entity Interpolation Part 2 of 6 - Clientside Input Buffering

by Christian Arellano on 11/04/16 01:50:00 pm   Featured Blogs

9 comments Share on Twitter    RSS

The following blog post, unless otherwise noted, was written by a member of Gamasutra’s community.
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.

 

In this article, we will implement a way of reducing the frequency at which clients send inputs to the server, in the same way that SyncVars are capped at 10 updates per second. We will do this by buffering inputs and sending them out at a given frequency. This way, we get transmission rate throttling for both inbound and outbound data, and more control over how we utilize network bandwidth.

Because of the way we split our networking code into smaller components in the previous article, it should be relatively easier for us to add our changes without having to wrangle through too much code.

Download The Source Code

If you haven't already, you can download the source code for this article. Also included in the download are the project folders for the upcoming articles in this series, so if you want to, you can skip ahead and see how the full entity interpolation implementation looks like.

Buffering Commands

In Unity Networking, clients send input information to the server using Commands. Without buffering, what we did instead was call the corresponding Command every time input is made, potentially causing the client to call Commands on the server during every frame.

With input buffering, we take a different approach. When input is generated, instead of calling the corresponding Command immediately, we place the input in a buffer:

// in Awake ():
List<Vector2> inputBuffer = new List<Vector2> ();

// in FixedUpdate ():
Vector2 input = /* poll input device here */;
inputBuffer.Add (input);

Immediately after we buffer the captured input, we check to see if the buffer is full. If it is, we call the appropriate Command and send the buffered inputs to the server.

// Since FixedUpdate runs at 50 times a second,
// we set inputBufferSize to 5 so that we can send
// our inputs to the server at 10 times a second.
public int inputBufferSize = 5;

// back to FixedUpdate ():
if (inputBuffer.Count < player.inputBufferSize) return;
player.CmdMove (inputBuffer.ToArray ());

// don't forget to make room for new inputs!
inputBuffer.Clear ();

Batching on the Server

Since we're now sending multiple inputs at a time to the server, we have to change our Command's function signature so that it can accept arrays:

[Command(channel=0)] public void CmdMove (Vector2[] inputs) {
    server.Move (inputs);
}

Once we receive the inputs on the server, we can apply them all in one go by iterating on the inputs array (similar to how we do client side prediction and server reconciliation):

public void Move (Vector2[] inputs) {
    CubeState serverState = player.serverState;
    foreach (Vector2 input in inputs) {
        serverState = CubeState.Move (serverState, input);
    }
    player.serverState = serverState;
}

And that does it for buffering!

Choppy Movement

When controlling your own player object, client prediction does a very good job of making sure that the experience always stays smooth and responsive. However, by introducing input buffering, other players will not see you in the same way that you see yourself! Since inputs are received at a low frequency and applied in batches, your movement will probably look choppy. You won't necessarily be slower; in fact you would probably move at the same speed as everyone else. However, visually it will seem that you're being rendered at a lower frame rate. This is expected - once we add interpolation in, your movement should become smooth again.

Speed Hacks

Our current implementation has a flaw that cheaters can take advantage of. Can you spot it?

What happens if the client sends more than 5 inputs in a single Command? What if it sends 10, or 50, or more? When the server receives the batched inputs, it accepts and applies all of them at the same time, regardless of the number of inputs received. This allows the client to make more moves than it should be allowed to in a given time frame. The server could potentially let you take 100 steps when you would normally be allowed to take only 5 steps, giving you an unfair advantage over other players. In multiplayer games, this is called a "speed hack," and we will look into how we can prevent this in the next article.

To see all of this in action on your own machine, be sure to download the project folder for this article! Thank you for reading, and until next time.


Related Jobs

Snowcastle Games
Snowcastle Games — Oslo, Norway
[11.20.18]

Gameplay Programmer
Game Changer
Game Changer — Remote Work From Anywhere, Kansas, United States
[11.20.18]

Mobile Game Programmer
Deep Silver Volition
Deep Silver Volition — Champaign, Illinois, United States
[11.19.18]

Mid/Senior Multiplayer Programmer
Cryptic Studios
Cryptic Studios — Los Gatos, California, United States
[11.19.18]

Software Engineer, Audio





Loading Comments

loader image