Search Unity

Unity Multiplayer UNET Message Inheritance Broken

Discussion in 'Connected Games' started by Zullar, Nov 24, 2015.

  1. Zullar

    Zullar

    Joined:
    May 21, 2013
    Posts:
    621
    I am using messages, with child messages that contains additional bits of payload data in addition to the parent payload data. However, it does not seem that messages can handle a data payload split between parent and child. It does not throw errors, but the data does not get sent correctly.

    My debug log reads this as being sent/recieved
    MsgOut: KeyAudioClipIndex = 2 and Vec3=(2.4, 0.0, 1.1)
    MsgIn: KeyAudioClipIndex = 0 and Vec3=(2.4, 0.0, 1.1)
    ***The short data is lost (sent as a value of 2, but received as a value of 0), but the Vec3 is sent.

    However if I put all data in the child message class, then it works fine. (Both the short and vec3 are sent correctly)
    MsgOut: KeyAudioClipIndex = 2 and Vec3=(2.4, 0.0, 1.1)
    MsgIn: KeyAudioClipIndex = 2 and Vec3=(2.4, 0.0, 1.1)
    ***The short data is sent correctly (sent value of 2, received a value of 2)

    This code causes issues with message data loss.
    Code (csharp):
    1.  
    2. public abstract class MessagePlayAudioEffect : MessageBase
    3. {
    4.     public short keyAudioClipIndex; //msgData, index of the KeyAudioClip being played
    5. }
    6.  
    7. public class MessagePlayAudioEffect3D : MessagePlayAudioEffect
    8. {
    9.     public Vector3 vector3; //msgData, position of effect
    10. }
    11.  
    This code works properly
    Code (csharp):
    1.  
    2. public abstract class MessagePlayAudioEffect : MessageBase
    3. {
    4.  
    5. }
    6.  
    7. public class MessagePlayAudioEffect3D : MessagePlayAudioEffect
    8. {
    9.     public short keyAudioClipIndex; //msgData, index of the KeyAudioClip being played
    10.     public Vector3 vector3; //msgData, position of effect
    11. }
    12.  
    Is message inheritance not supported, or bugged? Anybody else having this issue?

    As a work-around I can just copy and paste all fields into all message classes and not use inheritance. But this is very bad practice... you should never copy & paste code in multiple locations!!!

    Thanks in advance.
     
    Last edited: Nov 24, 2015
  2. Noshire1

    Noshire1

    Joined:
    Oct 20, 2014
    Posts:
    10
    Hi Zullar

    I ran into the same issue. I've researched and tried different ways. The only reliable way I found to get it working is by overriding the default Serialize() and Deserialize() implementations and call their base, like so:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Networking;
    3.  
    4. public abstract class MessagePlayAudioEffect : MessageBase {
    5.     public short keyAudioClipIndex; //msgData, index of the KeyAudioClip being played
    6.  
    7.     public override void Deserialize (NetworkReader reader) {
    8.         base.Deserialize (reader);
    9.         this.keyAudioClipIndex = reader.ReadInt16();
    10.     }
    11.  
    12.     public override void Serialize (NetworkWriter writer) {
    13.         base.Serialize (writer);
    14.         writer.Write(this.keyAudioClipIndex);
    15.     }
    16.  
    17. }
    18.  
    19. public class MessagePlayAudioEffect3D : MessagePlayAudioEffect {
    20.     public Vector3 vector3; //msgData, position of effect
    21.  
    22.     public override void Deserialize (NetworkReader reader) {
    23.         base.Deserialize (reader);
    24.         this.vector3 = reader.ReadVector3();
    25.     }
    26.  
    27.     public override void Serialize (NetworkWriter writer) {
    28.         base.Serialize (writer);
    29.         writer.Write(this.vector3);
    30.     }
    31. }
    You can see in the Documentation that, should you not provide your own overrides, Unity will in fact auto-generate default ones. I'm not sure if it's an oversight or if there's some possible problems related to auto-generating that, but the Unity-generated code does not call into base.Serialize() and base.Deserialize() sadly.

    This causes a bit of boilerplate code, but at least you also get more control over serialization as a benefit, and it keeps your Message hierarchy intact.

    Hope this helps!
     
    Zullar likes this.
unityunity