Search Unity

Build from different computer, same source = broken network

Discussion in 'Multiplayer' started by Toufinet, Mar 5, 2016.

  1. Toufinet

    Toufinet

    Joined:
    Jun 8, 2015
    Posts:
    6
    Hi,

    I'm building a game with a friend.
    Sources are synchronised with Subversion.

    When building the server ( linux standalone headless ) from my computer, then building for Windows, then running from my computer, it works.

    But when my friend builds the game from his side for Windows, then the network with -my-side-builded- Linux server is broken.

    It seems that we have to build the linux dedicated server AND the client from the same computer ( and I would even say, from the same "Unity process ID" .. because if I restart Unity between the Linux build and Windows build, the network is also broken ).

    Does this mean that, supposing both computers have exactly the same sources, it is not possible to build the game from both sides and have the network part working correctly ?

    Thank you for your help.
    Vincent.
     
  2. Freakyuno

    Freakyuno

    Joined:
    Jul 22, 2013
    Posts:
    138
    This doesn't sound like it should be a requirement, to build the server and client from the same unity instance.

    I bet in your network manager, you've got CRC matching turned on, which means that the CRC's of the client and the server executables much match what the server thinks they should be, or it wont let you connect. This prevents tampering with your executable and still being able to connect to your server.
     
  3. Oshroth

    Oshroth

    Joined:
    Apr 28, 2014
    Posts:
    99
    The CRC matching is only used for making sure there is the same NetworkBehaviours scripts running on the server and on the client, at least according to its code. I have had some similar issues where different builds have network issues when connected. It might be caused by differences in auto-generated network code.
     
  4. Freakyuno

    Freakyuno

    Joined:
    Jul 22, 2013
    Posts:
    138
    So I'm pretty sure that unity uses a PostSharp style of method injection. Do you think it's caused by the naming conventions in a system like that?
     
  5. Oshroth

    Oshroth

    Joined:
    Apr 28, 2014
    Posts:
    99
    Unity auto-generates NetworkSerialize/Deserialize() functions, and hashs for RPC & Command functions for each NetworkBehaviour. If it generates different hashs or wrong serialize order for the NetworkSerialize/Deserialize(), it would cause issues.

    Code (CSharp):
    1. static PlayerSyncer()
    2.     {
    3.         PlayerSyncer.kCmdCmdProvidePositionToServer = -501706433;
    4.         NetworkBehaviour.RegisterCommandDelegate(typeof(PlayerSyncer), PlayerSyncer.kCmdCmdProvidePositionToServer, new NetworkBehaviour.CmdDelegate(PlayerSyncer.InvokeCmdCmdProvidePositionToServer));
    5.         PlayerSyncer.kCmdCmdProvideRotationToServer = 318890644;
    6.         NetworkBehaviour.RegisterCommandDelegate(typeof(PlayerSyncer), PlayerSyncer.kCmdCmdProvideRotationToServer, new NetworkBehaviour.CmdDelegate(PlayerSyncer.InvokeCmdCmdProvideRotationToServer));
    7.         NetworkCRC.RegisterBehaviour("PlayerSyncer", 2);
    8.     }
    9.  
    10.     public override bool OnSerialize(NetworkWriter writer, bool forceAll)
    11.     {
    12.         if (forceAll)
    13.         {
    14.             writer.Write(this.syncPos);
    15.             writer.Write(this.syncRot);
    16.             writer.Write(this.playerColor);
    17.             return true;
    18.         }
    19.         bool flag = false;
    20.         if ((base.syncVarDirtyBits & 1u) != 0u)
    21.         {
    22.             if (!flag)
    23.             {
    24.                 writer.WritePackedUInt32(base.syncVarDirtyBits);
    25.                 flag = true;
    26.             }
    27.             writer.Write(this.syncPos);
    28.         }
    29.         if ((base.syncVarDirtyBits & 2u) != 0u)
    30.         {
    31.             if (!flag)
    32.             {
    33.                 writer.WritePackedUInt32(base.syncVarDirtyBits);
    34.                 flag = true;
    35.             }
    36.             writer.Write(this.syncRot);
    37.         }
    38.         if ((base.syncVarDirtyBits & 4u) != 0u)
    39.         {
    40.             if (!flag)
    41.             {
    42.                 writer.WritePackedUInt32(base.syncVarDirtyBits);
    43.                 flag = true;
    44.             }
    45.             writer.Write(this.playerColor);
    46.         }
    47.         if (!flag)
    48.         {
    49.             writer.WritePackedUInt32(base.syncVarDirtyBits);
    50.         }
    51.         return flag;
    52.     }