MonoTouch:通过GameKit发送/接收NSData

本文关键字:接收 NSData 发送 GameKit 通过 MonoTouch | 更新日期: 2023-09-27 18:32:40

我正在尝试在我的MonoTouch游戏中实现匹配。我已经成功地实现了通过GameKit连接玩家的系统,但我被困在发送和接收数据上。

如何将这个 objective-c 代码转换为 c#?我想发送的数据类型是具有XY浮点组件的Vector2类。

NSError *error;
PositionPacket msg;
msg.messageKind = PositionMessage;
msg.x = currentPosition.x;
msg.y = currentPosition.y;
NSData *packet = [NSData dataWithBytes:&msg length:sizeof(PositionPacket)];
[match sendDataToAllPlayers: packet withDataMode: GKMatchSendDataUnreliable error:&error];
if (error != nil)
{
    // handle the error
}

任何帮助将不胜感激!

MonoTouch:通过GameKit发送/接收NSData

由于OpenTK.Vector2是用[Serializable]装饰的,常见的方法是将结构序列化为Stream(例如MemoryStream(,然后从中初始化一个新的NSData,例如使用NSData.FromStream。这样做有相当多的开销,但它适用于任何结构。

Stream的更好用法是将您的值写入其中(例如,带有StreamWriter(。这消除了序列化开销(反射(,并允许您从不同的值生成流(无需创建结构(。

MemoryStream ms = new MemoryStream ();
using (StreamWriter sw = new StreamWriter (ms)) {
    sw.Write (v2.X);
    sw.Write (v2.Y);
}
ms.Position = 0;
var data = NSData.FromStream (ms);

一种更复杂(但可能更快(的方法是使用接受IntPtr(指针(和数据大小的unsafe代码和NSData.FromBytes。如果您的所有数据都已经在结构中,那么这很容易做到。

黑客方法是将Vector2转换为monotouch.dll中已知的类型,例如 PointF .这将允许您使用 NSData.FromObject .此 API 适用于NSObject、最基本的值类型和NSValue支持或monotouch.dll内部添加的一些基本类型,例如 RectangleFPointF , ...

var v2 = new OpenTK.Vector2 ();
var pt = new System.Drawing.PointF (v2.X, v2.Y);
var data = NSData.FromObject (pt);

好的,所以我想我在很大程度上都想通了。对于任何感兴趣的人,这是我的解决方案。

unsafe
{
    NSError error = new NSError((NSString)"Test", 0);
    System.IntPtr pointer = Marshal.AllocHGlobal(sizeof(PointF));
    PointF packedData = new PointF(position.X, position.Y);
    Marshal.StructureToPtr(packedData, pointer, false);
    NSData packet = NSData.FromBytes(pointer, (uint)sizeof(PointF));
    currentMatch.SendDataToAllPlayers(packet, GKMatchSendDataMode.Unreliable, error.ClassHandle);
    Marshal.FreeHGlobal(pointer);
}

所以我仍然不确定NSError应该是什么,尽管对于我的项目来说,失败的数据包并不重要。这是接收数据包的代码。

PointF packedData = (PointF)Marshal.PtrToStructure(data.Bytes, typeof(PointF));
var recievedData = new Vector2(packedData.X, packedData.Y);