Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

How to SendMessage List<Custom Class> ?

Discussion in 'Multiplayer' started by Leoo, Sep 24, 2015.

  1. Leoo

    Leoo

    Joined:
    May 13, 2013
    Posts:
    96
    Hello guys,

    Am having this particular problem trying to send a List<Cube> within a CubeMessage : MessageBase.

    There is something i can't see, what is the right pipeline for doing this?

    Code (csharp):
    1.  
    2. ....
    3.     public static List<Cube> cubes;
    4.    
    5.     void Start(){  //Initialization method.
    6.          cubes = new List<Cube>();
    7.           ...      <-  A few lines of code that add a few cubes to it.
    8.      }
    9.    
    10.  
    11.  
    12.     public class CubeListMessage : MessageBase{
    13.  
    14.         public List<Cube> cubeList;
    15.  
    16.         public CubeListMessage(){
    17.             cubeList = new List<Cube>();
    18.         }
    19.      }
    20.  
    21.     [System.Serializable]
    22.     public class Cube {
    23.         public Vector3 position;
    24.         public Quaternion resourceRotation;
    25.         public Color resourceColor;
    26.  
    27.     }
    28.  
    29.     public void SendList(NetworkConnection conn){
    30.         //Create a new CubeListMessage
    31.         CubeListMessage msg = new CubeListMessage();
    32.         //Put this base cube list List<Cube> cubes;
    33.         //into the cubelist inside the CubeListMessage
    34.         msg.cubeList = cubes;
    35.         //Send the Message
    36.         conn.SendByChannel(MyMsgTypes.MSG_CUBELIST, msg, 1);
    37.     }
    38.  
    39. public void GetList(NetworkMessage netMsg){
    40.         //Read the message into a CubeListMessage : MessageBase class.
    41.         CubeListMessage msg = netMsg.ReadMessage<CubeListMessage>();
    42.  
    43.         //Override this base cube list List<Cube> cubes, into
    44.         //this new one i got inside the Message
    45.         cubes = msg.cubeList;
    46.      
    47.         //CHECK:  Let's see if the CubeList made it.
    48.         Debug.Log(cubes.Count);                      // <---- ERROR
    49. }
    50.  
    51.  
    The error: NullReferenceException: Object reference not set to an instance of an object , on the Debug Line!

    There is something wrong with the Serialization of the List<Cube> cubeList inside the Message, if i add a random value and try to get it at the getlist method it comes perfectly, maybe ill have to do the serialization by hand with NetworkWriter? how should i do this?

    Thaanks!!
    -Leo
     
    Last edited: Sep 24, 2015
  2. Noob4Sale

    Noob4Sale

    Joined:
    Mar 10, 2015
    Posts:
    11
    Are you Initializing the cubes list @ line 3?
     
    Leoo likes this.
  3. Leoo

    Leoo

    Joined:
    May 13, 2013
    Posts:
    96
    Oh yeah sorry, Updated the post to show my initialization method , "start";
    Thanks for catching that up!
     
  4. Noob4Sale

    Noob4Sale

    Joined:
    Mar 10, 2015
    Posts:
    11
    Is it attached to a gameobject in the scene?
     
  5. Leoo

    Leoo

    Joined:
    May 13, 2013
    Posts:
    96
    Yes, this code is working as intended IF i just put a "int example = 0" instead of my custom Cube class to serialize on the message. i feel like there is something wrong about line .41
     
  6. Noob4Sale

    Noob4Sale

    Joined:
    Mar 10, 2015
    Posts:
    11
    Have you tried assigning values to the cube objects which get added to the List? Also a person could also send the data over the net as a byte array,example(not sure if it'll work):
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Networking;
    3. using System.Collections.Generic;
    4. using System.Runtime.Serialization.Formatters.Binary;
    5. using System.IO;
    6.  
    7.  
    8.     public class Example : MonoBehaviour
    9.     {
    10.     public static List<Cube> cubes;
    11.  
    12.         void Start()
    13.         {  //Initialization method.
    14.             cubes = new List<Cube>();
    15.          }
    16.  
    17.         public class CubeListMessage : MessageBase
    18.         {
    19.             public List<Cube> cubeList;
    20.             public CubeListMessage()
    21.             {
    22.                 cubeList = new List<Cube>();
    23.             }
    24.         }
    25.  
    26.         [System.Serializable]
    27.         public class Cube
    28.         {
    29.             public Vector3 position;
    30.             public Quaternion resourceRotation;
    31.             public Color resourceColor;
    32.  
    33.         }
    34.  
    35.         public void SendList(NetworkConnection conn)
    36.         {
    37.             BinaryFormatter bf = new BinaryFormatter();
    38.             MemoryStream ms = new MemoryStream();
    39.             bf.Serialize(ms, cubes);
    40.             NetworkWriter nw = new NetworkWriter();
    41.             nw.StartMessage(MyMsgTypes.MSG_CUBELIST);
    42.             nw.WriteBytesFull(ms.ToArray());
    43.             ms.Dispose();
    44.             nw.FinishMessage();
    45.             conn.SendWriter(nw,1 );
    46.         }
    47.  
    48.         public void GetList(NetworkMessage netMsg)
    49.         {
    50.             CubeListMessage msg = netMsg.ReadMessage<CubeListMessage>();
    51.             BinaryFormatter bf = new BinaryFormatter();
    52.             MemoryStream ms = new MemoryStream(netMsg.reader.ReadBytesAndSize());
    53.             cubes = (List< Cube >)bf.Deserialize(ms);
    54.             ms.Dispose();
    55.             Debug.Log(cubes.Count);                  
    56.         }
    57.     }
     
    Leoo likes this.
  7. Leoo

    Leoo

    Joined:
    May 13, 2013
    Posts:
    96
    Still trying to test it, going workarounds to get the Quaternion and the Vector3 to the other side, i thought these structs were already Serializable... o_O

    Dude, thanks a loot! i think this is the right way to do this , doing your own serialization to the classes, now ill work to get those vector3 and quaternions to the other side..

    I feel kindda tricked by UNET, at the end am just doing a serialization and sending it as byte, as i did before on raknet, can't use any of the automatic serialization or "message base" things... like dah..
     
    Last edited: Sep 24, 2015
  8. Darhkuan

    Darhkuan

    Joined:
    Feb 24, 2014
    Posts:
    21
    Hi Leoo & Noob4Sale,

    Did you end up finalising a solution to this?

    I think I'm in the same boat as you Leoo, believing UNET was going to take care of my serialisation for complex strucs (including lists of items) rather than me having to manage it separately as I always have. Kinda defeats the whole purpose of the message base for anything but the simple comms.
     
  9. Noob4Sale

    Noob4Sale

    Joined:
    Mar 10, 2015
    Posts:
    11
    You can use the binaryformatter(binarywriter/protobuf/msgpack etc,.) to serialize any of the data into a memory stream and then send it over as a byte array,just make sure the datatype is marked as [serializable] and instead of using Vectors use floats or your own struct.
     
    Leoo likes this.
  10. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    UNet MessageBase serialization does not support generic container classes. It does support arrays.