Input Updates Best Practice?

I’m currently working on a multiplayer game and came upon the question of which way would be best to send the input from the client to the server…

Here are the 3 methods I thought of…

  • Always send all input even if it hasn’t changed:
CmdSendInputToServer( vertical, horizontal, sprint, jump );
  • Send only changed input, but each one sends its own separate RPC:
if ( vertical != verticalLastSent ) CmdSendVerticalToServer( vertical );
if ( horizontal != horizontalLastSent ) CmdSendHorizontalToServer( horizontal );
if ( sprint != sprintLastSent ) CmdSendSprintToServer( sprint );
if ( jump != jumpLastSent ) CmdSendJumpToServer( jump );
  • Package up only the changed input into a struct and send that:
struct Input {
  float vertical;
  float horizontal;
  bool sprint;
  bool jump;
}

Input input = new Input();

if ( vertical != verticalLastSent ) input.vertical = vertical;
if ( horizontal != horizontalLastSent ) input.horizontal = horizontal;
if ( sprint != sprintLastSent ) input.sprint = sprint;
if ( jump != jumpLastSent ) input.jump = jump;

CmdSendInputToServer( input );

This one seems like the best of the 3 (I think), but I can’t be sure. Wouldn’t it still be sending the entire struct even if you don’t explicitly set certain values? Plus, I read that sending structs is best avoided whenever possible.

Which of those would be the best on bandwidth, etc? Or is there any difference?

Also, is there another method that I haven’t thought of?

Obviously the above code is nowhere complete, just more of an example to help get the idea across.

I’ve been doing a lot of searching and reading various tutorials, etc but nothing seems to address this specific issue. Most tutorials I’ve seen simply use some variation of the first item in my list above, so it would seem that is the way you’re supposed to do it, but that doesn’t seem very good when it comes to bandwidth. Especially when with input you’re usually sending it pretty much every frame or so.

Sorry if this has been talked about and I just couldn’t find it…

I’m still pretty new to Unet and Unity as a whole, so sorry if this question is kinda “noobish”.

Thanks for any info! :slight_smile:

It depends on what protocol you are using. A fast paced game in which you are constantly sending your input should be using UDP, so if that’s the case, you need to keep in mind that a packet may get lost. So if you are only sending input that changed client-side without any server confirmation, the information about what input have and havent been changed can quickly get desynced.
And also, given that you want to use the aproach of sending each input command instead of final information about character state, means that you want server to do the “actual” calculations and the client to do predictions. In that case, you should read this:
https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking
You are going to solve problems far more complex than optimizing input packet size, because to implement this aproach properly, you are going to be labeling each input packet with a number, have server confirming the last recieved input packet along with other game state information to do the prediction. Also you don’t send input commands every frame - you pack several commands together and send them at a fixed rate (the article has it all, there is a lot to explain).
The thing is, even though this aproach makes up for a pretty solid consistent and cheat-resistant netcode, it’s pretty hard to implement and it is bandwidth-heavy in general. I actually decided against it because I don’t quite understand how do the prediction part as it involves doing multiple physics steps for a single object in one frame. (I managed to get it working, but not in unity)
Simply handling your character movement on the client, sending the position at a fixed rate and then interpolating it on the server is a lot easer to do.

Yeah, I got stuck on that same part. Even the unity devs seem to link people to that same article from valve and yet…the solution presented there can’t even be implemented in Unity (at least I’ve never been able to find a way).