【问题标题】:Sending an array of primitive types over a ClientRPC call通过 ClientRPC 调用发送原始类型数组
【发布时间】:2016-11-09 14:33:24
【问题描述】:

我正在尝试使用ClientRpc 属性通过网络发送各种基本类型的数组。 documentation 声明,我可以毫无问题地通过网络发送这些:

  • 基本类型(byte、int、float、string、UInt64 等)
  • 基本类型数组

但是,将它们混合在 object[] 数组中似乎不起作用。我有以下示例:

[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});
    }
}

在服务器上,我得到了输出

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

在客户端,这没有任何错误:

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

如何通过 ClientRpc 调用发送具有不同基本类型的各种数量的参数?

【问题讨论】:

  • 但它正在工作,不是吗?您可以通过强制转换为客户端上所需的任何原始类型来拆箱值。我真的不知道是什么问题。
  • 问题是我不知道客户端的类型。请注意,GetType() 为您提供了运行时的实际类型,它丢失了
  • 你试过if(o is System.String)然后投了吗?
  • o is System.String 返回 false。接收端的对象似乎是空对象,因为它们的 ToString 产生 System.Object。我更新了问题以包含每个对象的字符串表示
  • 我明白了,现在我明白了问题所在。我会试着找到一些东西。

标签: unity3d rpc unity5 unity3d-unet


【解决方案1】:

一种可能的解决方法是手动序列化数组并将其作为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);
    }
}

客户端和服务器端的输出和预期的一样。

【讨论】:

  • 我也在考虑。谢谢 - 将来会很有用。
  • 请注意,这种方法是有限制的,因为您不能包含 Unity 本来可以发送的某些类型,例如 Networked GameObjects
  • 另一个缺点是来自System.Runtime.Serialization.Formatters.BinaryBinaryFormatter 在很多.NET 子集上不可用。这可以通过使用另一个更广泛可用的序列化器来解决,例如XmlSerializer
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-12
  • 2016-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多