2

I am trying to send an array of various basic types over the Network using the ClientRpc attribute. The documentation states, that I can send these over the Network without problems:

  • basic types (byte, int, float, string, UInt64, etc)
  • arrays of basic types

However, it seems holding them mixed together in an object[] array does not work. I have the following example:

[Command]
void CmdForwardEvent(string eventName, object[] args) {
    Debug.Log ("Broadcasting event: " + eventName);
    foreach (var o in args) {
        Debug.Log ("arg-class: " + o.GetType() + ": " + o);
    }
    RpcForwardEvent (eventName, args);
}

[ClientRpc]
void RpcForwardEvent(string eventName, object[] args) {
    Debug.Log ("Received event " + eventName);
    foreach (var o in args) {
        Debug.Log ("arg-class: " + o.GetType() + ": " + o);
    }
}

void Update() {
    if (Input.GetKeyDown (KeyCode.P)) {
        CmdForwardEvent("Testevent", new object[]{"some string", 1, false});
    }
}

On the server, I get the output

Broadcasting event: Testevent
arg-class: System.String: some string
arg-class: System.Int32: 1
arg-class: System.Boolean: false

On the client, this arrives without any errors:

Received event: Testevent
arg-class: System.Object: System.Object
arg-class: System.Object: System.Object
arg-class: System.Object: System.Object

How can I send various amounts of arguments with different basic types over a ClientRpc call?

Felk
  • 7,720
  • 2
  • 35
  • 65
  • But it is working, isn't it? You can just unbox the values with casting to whatever primitive type you want on client. I don't really know what is the problem. – Jerry Switalski Jul 07 '16 at 10:41
  • The problem is that I don't know the Type on the Client side. Note that `GetType()` gives you the _actual type at runtime_, which got lost – Felk Jul 07 '16 at 10:43
  • Did you try `if(o is System.String)` and then cast it? – Jerry Switalski Jul 07 '16 at 10:45
  • `o is System.String` returns false. The objects on the receiving end seem to be empty object, because their ToString yields `System.Object`. I updated the question to include each object's string representation – Felk Jul 07 '16 at 10:54
  • I see thanks, now I see the problem. I will try to find something. – Jerry Switalski Jul 07 '16 at 10:56

1 Answers1

1

A possible workaround would be to manually serialize the array and send it as byte[]:

// new code

private BinaryFormatter bf = new BinaryFormatter();

private byte[] objectToBytes(object os) {
    MemoryStream stream = new MemoryStream ();
    bf.Serialize (stream, os);
    return stream.ToArray ();
}

private object bytesToObject(byte[] bytes) {
    MemoryStream stream = new MemoryStream (bytes);
    return bf.Deserialize (stream);
}

// modified code:

[Command]
void CmdForwardEvent(string eventName, byte[] argsAsBytes) {
    object[] args = bytesToObject(argsAsBytes) as object[];  // deserialize
    Debug.Log ("Broadcasting event: " + eventName);
    foreach (var o in args) {
        Debug.Log ("arg-class: " + o.GetType() + ": " + o);
    }
    RpcForwardEvent (eventName, argsAsBytes);
}

[ClientRpc]
void RpcForwardEvent(string eventName, byte[] argsAsBytes) {
    object[] args = bytesToObject(argsAsBytes) as object[];  // deserialize
    Debug.Log ("Received event " + eventName);
    foreach (var o in args) {
        Debug.Log ("arg-class: " + o.GetType() + ": " + o);
    }
}

void Update() {
    if (Input.GetKeyDown (KeyCode.P)) {
        // serialize
        byte[] bytes = objectToBytes(new object[]{"some string", 1, false});
        CmdForwardEvent("Testevent", bytes);
    }
}

output on client and server side are the same then, as expected.

Felk
  • 7,720
  • 2
  • 35
  • 65
  • I was think about it too. Thanks - can be usefull in the future. – Jerry Switalski Jul 07 '16 at 11:32
  • Note that this approach is limiting, as you can't include some types Unity can otherwise natively send, like Networked GameObjects – Felk Jul 07 '16 at 11:35
  • Another drawback is that the `BinaryFormatter` from `System.Runtime.Serialization.Formatters.Binary` isn't available on a lot of .NET subsets. This can be fixed by using another, more widely available Serializer like the `XmlSerializer` – Felk Jul 07 '16 at 13:09