Search Unity

Need help with custom messages

Discussion in 'Multiplayer' started by ZefanS, Jul 7, 2015.

  1. ZefanS

    ZefanS

    Joined:
    Jun 22, 2015
    Posts:
    18
    I have been attempting to solve a player - object communication problem using messages, and need to create a custom message that contains both an integer and a string. I tried to follow the example from the documentation, but have been getting inconsistent results and some strange errors.

    When running with only a host present, there are no runtime errors, but the string in the message received in the client callback is empty. When running with a host and a client present, if the client sends a message an IndexOutOfRangeException occurs in the server callback.

    This is my message handling script. It's currently attached to my player prefab:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Networking;
    3. using UnityEngine.Networking.NetworkSystem;
    4. using System.Collections;
    5.  
    6. public class RotationHandler : NetworkBehaviour
    7. {
    8.  
    9.     public class DataMsgType
    10.     {
    11.         public static short ROT_MSG = MsgType.Highest + 1;
    12.     };
    13.  
    14.     public class RotationMessage : MessageBase
    15.     {
    16.         public int dir;
    17.         public string obj;
    18.     };
    19.  
    20.     NetworkClient client;
    21.  
    22.     public GameObject datum;
    23.  
    24.     // Use this for initialization
    25.     void Start ()
    26.     {
    27.         NetworkManager netManager = GameObject.FindObjectOfType<NetworkManager>();
    28.         client = netManager.client;
    29.         if (client.isConnected)
    30.         {
    31.             client.RegisterHandler(DataMsgType.ROT_MSG, ClientReceiveRotMessage);
    32.         }
    33.         if (isServer)
    34.         {
    35.             NetworkServer.RegisterHandler(DataMsgType.ROT_MSG, ServerReceiveRotMessage);
    36.         }
    37.     }
    38.  
    39.     // Update is called once per frame
    40.     void Update ()
    41.     {}
    42.  
    43.     public void SendRotMessage(int rot, string obj)
    44.     {
    45.         RotationMessage rotMsg = new RotationMessage();
    46.  
    47.         rotMsg.dir = rot;
    48.         rotMsg.obj = obj;
    49.  
    50.         Debug.Log ("Rot: " + rot + " Obj: " + obj); //This prints out the rot and object name correctly
    51.  
    52.         if (isServer)
    53.         {
    54.             Debug.Log ("Server Message");
    55.             NetworkServer.SendToAll (DataMsgType.ROT_MSG, rotMsg);
    56.         }
    57.         else if (client.isConnected)
    58.         {
    59.             Debug.Log("Client Message");
    60.             client.Send(DataMsgType.ROT_MSG, rotMsg);
    61.         }
    62.     }
    63.  
    64.     public void ServerReceiveRotMessage(NetworkMessage netMsg)
    65.     {
    66.         Debug.Log("Server Callback"); //Somewhere after this message an IndexOutOfRangeException occurs
    67.         int dir = netMsg.ReadMessage<RotationMessage>().dir;
    68.         string obj = netMsg.ReadMessage<RotationMessage>().obj;
    69.         RotationMessage test = netMsg.ReadMessage<RotationMessage>();
    70.         Debug.Log("Server" + test);
    71.         SendRotMessage(dir, obj);
    72.     }
    73.  
    74.     public void ClientReceiveRotMessage(NetworkMessage netMsg)
    75.     {
    76.         //Debug.Log("Client Callback");
    77.  
    78.         if (isServer && isClient)
    79.         {
    80.             Debug.Log("Host Action");
    81.  
    82.             int dir = netMsg.ReadMessage<RotationMessage>().dir;
    83.             string obj = netMsg.ReadMessage<RotationMessage>().obj;
    84.  
    85.             Debug.Log (dir); //The dir is correct
    86.             Debug.Log (obj); //Obj is blank
    87.             datum = GameObject.Find(obj); //datum is NULL
    88.  
    89.             if (datum != null && client.isConnected)
    90.             {
    91.                 if (dir == 1)
    92.                 {
    93.                     Debug.Log("1 for Up");
    94.                     datum.GetComponent<ApplyRotation>().RotateUp();
    95.                 }
    96.                 else if (dir == 2)
    97.                 {
    98.                     Debug.Log("2 for Down");
    99.                     datum.GetComponent<ApplyRotation>().RotateDown();
    100.                 }
    101.                 else if (dir == 3)
    102.                 {
    103.                     Debug.Log("3 for Right");
    104.                     datum.GetComponent<ApplyRotation>().RotateRight();
    105.                 }
    106.                 else if (dir == 4)
    107.                 {
    108.                     Debug.Log("4 for Left");
    109.                     datum.GetComponent<ApplyRotation>().RotateLeft();
    110.                 }
    111.             }
    112.             else
    113.             {
    114.                 Debug.Log("Datum is NULL");
    115.             }
    116.         }
    117.     }
    118. }
    119.  
    The exact error issued is:
    This is the first time I've worked on code using messages. It seemed to be working when I was only sending integers using the default IntegerMessage class, but not now that I'm using my custom message. If someone could point me in the right direction I would appreciate it a lot.
     
  2. peterept

    peterept

    Joined:
    Dec 6, 2012
    Posts:
    22
    I don't think you should be calling ReadMessage<>() multiple times. Once you've read it once you have fully deserialized it. Calling it again will attempt to read from the end of the buffer and will throw the error you see.

    It should be:

    Code (CSharp):
    1. RotationMessage rotMsg = netMsg.ReadMessage<RotationMessage>();
    2. rotMsg.dir ... etc
     
    Korial likes this.
  3. ZefanS

    ZefanS

    Joined:
    Jun 22, 2015
    Posts:
    18
    Ya, that was it. Thanks!