Serialize a custom class

Options
Hello everybody,

I am trying to make this class serializable so that it can be sent over the network:
public class DamageEventArgs
    {
        public PhotonPlayer attacker = null;
        public string weapon = "";
        public string hitTransformName = "";
        public string hitBoxName = "";
        public Vector3 hitDirection = default(Vector3);
        public Vector3 hitPosition = default(Vector3);
        public int damage = 0;
    }

Now this is sort of what I am trying to serialize it:
private static byte[] SerializeDamageEventArgs(object customobject)
    {
       DamageEventArgs damageData = (DamageEventArgs)customobject;

        byte[] playerByte = SerializePhotonPlayer(damageData.attacker);

        /* need a byte array for the length of the string since it's dynamic */
        byte[] weaponLengthByte = Protocol.Serialize(damageData.weapon);
        byte[] weaponByte = Protocol.Serialize(damageData.weapon.Length);


        byte[] hitTransformLengthByte = Protocol.Serialize(damageData.hitTransformName.Length);
        byte[] hitTransformByte = Protocol.Serialize(damageData.hitTransformName);

        byte[] hitBoxNameLengthByte = Protocol.Serialize(damageData.hitBoxName.Length);
        byte[] hitBoxNameByte = Protocol.Serialize(damageData.hitBoxName);

        byte[] hitDirectionByte = SerializeVector3(damageData.hitDirection);
        byte[] hitPositionByte = SerializeVector3(damageData.hitPosition);

        byte[] damageByte = Protocol.Serialize(damageData.damage);

        byte[] serializedData = new byte[playerByte.Length + weaponByte.Length + weaponLengthByte.Length + hitTransformLengthByte.Length + hitTransformByte.Length
            +hitBoxNameLengthByte.Length + hitBoxNameByte.Length + hitDirectionByte.Length + hitPositionByte.Length + damageByte.Length];

        /* combine all the arrays here */

        return serializedData;
    }

Now I ask whether this is really the way to approach this.

Thanks in advance. :)

Comments

  • vadim
    Options
    When serializing, you put your class data in byte[] from which later you can retrieve those data. So always write 'deserialize' method in parallel to make sure that you don't put excess information. For instance, you do not need string length when serializing 'string' (you will not use it in 'deserialize' ).
    Also check if sent data is useful on receiving side. Does physics parameters like hitDirection makes sense for non-owner?

    Note also: to make code simpler you can put all required data in Object[] and serialize/deserialize it with one call with some traffic overhead. Or use resulting Object[] directly instead of your class instance (no custom serialization at all).
  • Thanks for your advice.

    I think I need to send the hitDirection parameter because it's something that's used to cause a ragdoll death with a certain force for everyone if the player dies. I don't know before I sent the data whether the player is going to get killed by the damage (it's checked on the server).

    I've been thinking about putting all data in an Object[] and maybe have something in the class itself that allows this conversion from class to object and visa versa, it sounds nice, but I think I prefer that you don't have to think about the serialization anymore at all once you've added it to the custom types.

    So something like this would work? (with PhotonPeer.RegisterType also done)
    private static byte[] SerializeDamageEventArgs(object customobject)
        {
           DamageEventArgs damageData = (DamageEventArgs)customobject;
    
            byte[] playerByte = SerializePhotonPlayer(damageData.attacker);
            byte[] weaponByte = Protocol.Serialize(damageData.weapon.Length);
            byte[] hitTransformByte = Protocol.Serialize(damageData.hitTransformName);
            byte[] hitBoxNameByte = Protocol.Serialize(damageData.hitBoxName);
            byte[] hitDirectionByte = SerializeVector3(damageData.hitDirection);
            byte[] hitPositionByte = SerializeVector3(damageData.hitPosition);
            byte[] damageByte = Protocol.Serialize(damageData.damage);
    
            byte[] serializedData = new byte[playerByte.Length + weaponByte.Length + hitTransformByte.Length
                + hitBoxNameByte.Length + hitDirectionByte.Length + hitPositionByte.Length + damageByte.Length];
    
            /* combine all the arrays here */
    
            return serializedData;
        }
    
        private static object DeserializeDamageEventArgs(byte[] bytes)
        {
            DamageEventArgs o = new DamageEventArgs();
    
            o.attacker = (PhotonPlayer)DeserializePhotonPlayer(bytes);
            o.weapon = (string)Protocol.Deserialize(bytes);
            o.hitTransformName = (string)Protocol.Deserialize(bytes);
            o.hitBoxName = (string)Protocol.Deserialize(bytes);
            o.hitDirection = (Vector3)DeserializeVector3(bytes);
            o.hitPosition = (Vector3)DeserializeVector3(bytes);
            o.damage = (int)Protocol.Deserialize(bytes);
    
            return o;
        }
    
  • vadim
    Options
    Why don't to try it and see if it works?
    Without test, I see only one problem with your code. Each value is deserialized form position 0 of 'bytes' array. You need to offset it to proper position.