Search Unity

Custom Message int32 is lost in serialization

Discussion in 'Multiplayer' started by PaulRdy, Jul 25, 2017.

  1. PaulRdy

    PaulRdy

    Joined:
    Jun 26, 2015
    Posts:
    17
    Hey guys,
    I'm having yet another UNET serialization issue. I'm currently making a networked CCG with UNET and am using custom messages for much of my communication.

    However now one message is not returning the correct value from the NetworkReader.ReadInt32() method.

    Here's the code:

    Code (CSharp):
    1.  
    2. public void RequestSetDeck(List<Card> deck_, int playerID_)
    3.     {
    4.         the_client.Send(GameConfig.DeckNetworkMessage, new DeckMessage(deck_, playerID_));
    5.     }
    6.  
    7.     private void SERVER_OnSetDeckRequestRecieved(NetworkMessage netMsg)
    8.     {
    9.         DeckMessage m = netMsg.ReadMessage<DeckMessage>();
    10.         Debug.Log(m.playerID);
    11.         Debug.Log(m.cards[29].id);
    12.         try
    13.         {
    14.             if (m.playerID == 0)
    15.             {
    16.                 instance.the_match.player1.SetDeck(m.cards);
    17.                 instance.RpcDeckSetConfirmed(m.playerID);
    18.             }
    19.             else if (m.playerID == 1)
    20.             {
    21.                 instance.the_match.player2.SetDeck(m.cards);
    22.                 instance.RpcDeckSetConfirmed(m.playerID);
    23.             }
    24.  
    25.         }
    26.         catch (DeckInvalidException e)
    27.         {
    28.             instance.RpcDeckSetDenied(m.playerID);
    29.         }
    30.         catch (Exception e)
    31.         {
    32.             Debug.LogException(e);
    33.         }
    34.     }
    35.  
    Debug.Log(m.playerID) writes 3474792 to the console log eventhough playerID in RequestSetDeck is 0. If I hardcode a number into the Serialize method in my DeckMessage class the Log still prints 3474792.

    Debug.Log(Debug.Log(m.cards[29].id)) throws an IndexOutOfBounds Exception eventhough the list during serialization has 30 entries.

    Here is my Message class:
    Code (CSharp):
    1.  
    2. public class DeckMessage : MessageBase
    3.     {
    4.         public List<Card> cards;
    5.         public int playerID;
    6.  
    7.         public DeckMessage () { }
    8.         public DeckMessage(List<Card> data_, int playerID_)
    9.         {
    10.             cards = new List<Card>();
    11.             playerID = playerID_;
    12.             foreach (Card c in data_)
    13.             {
    14.                 cards.Add(c);
    15.             }
    16.         }
    17.  
    18.         public override void Serialize(NetworkWriter writer)
    19.         {
    20.             writer.StartMessage(GameConfig.DeckNetworkMessage);
    21.  
    22.             writer.Write(playerID);
    23.  
    24.             for (int i = 0; i < GameConfig.deckSize; i++)
    25.             {
    26.                 if (i >= cards.Count || cards[i] == null)
    27.                 {
    28.                     writer.Write(false);
    29.                     continue;
    30.                 }
    31.                 else
    32.                 {
    33.                     writer.Write(true);
    34.                     cards[i].Serialize(writer);
    35.                 }
    36.  
    37.             }
    38.             writer.FinishMessage();
    39.         }
    40.  
    41.         public override void Deserialize(NetworkReader reader)
    42.         {
    43.             this.cards = new List<Card>();
    44.  
    45.             this.playerID = reader.ReadInt32();
    46.  
    47.             for (int i = 0; i < GameConfig.deckSize; i++)
    48.             {
    49.                 if (!reader.ReadBoolean())
    50.                 {
    51.                     continue;
    52.                 }
    53.                 else
    54.                 {
    55.                     cards.Add(Card.Deserialize(reader));
    56.                 }
    57.             }
    58.         }
    59.     }
    60.  
    This pattern was working fine for other classes which had more data. Not sure what's causing this. Any help would be appreciated!
     
  2. PaulRdy

    PaulRdy

    Joined:
    Jun 26, 2015
    Posts:
    17
    I'm bumping this since I've managed to narrow down the problem. Still haven't found a fix yet though.
    Apparently the ReadInt32() Method is reading parts of the header from the message.

    If I change the MessageType from MsgType.Highest + 6 to something else the debugged number changes. No other modifications do anything though. Even commenting out the entire for-loop so I'm in essence just reading/writing the one int continues to be buggy.
     
  3. PaulRdy

    PaulRdy

    Joined:
    Jun 26, 2015
    Posts:
    17
    Okay, I've managed to find a workaround and what the issue is. Still not sure what causes it though.

    Apparently when sending a NetworkMessage from client to server the Serialize function writes the message ID at the start of the message and the Deserialize function starts reading at that message ID.

    This is not the case when sending from server to client.

    Code (CSharp):
    1. public override void Deserialize(NetworkReader reader)
    2.         {
    3.             this.cards = new List<Card>();
    4. // read 4 bytes to skip the int32 written containing the message ID
    5.             reader.ReadBytes(4);
    6.             this.playerID = reader.ReadInt32();
    7.  
    8.             for (int i = 0; i < GameConfig.deckSize; i++)
    9.             {
    10.                 if (!reader.ReadBoolean())
    11.                 {
    12.                     continue;
    13.                 }
    14.                 else
    15.                 {
    16.                     cards.Add(Card.Deserialize(reader));
    17.                 }
    18.             }
    19.         }
    This works as intended. However, I'm pretty sure this entire thing is a bug.