我正在做一个基于MPC框架的多人游戏,用于玩家设备之间的数据通信(以及游戏的spritekit)。
逻辑是其中一个设备是主设备,执行所有游戏逻辑和计算,并将各种精灵的位置发送到只需更新精灵位置的从设备。
主人打开他和所有奴隶之间的流,并通过这些流发送各种数据。数据存储在类型(String,Any)的字典中。
问题有两个:
我已经进行了各种检查和控制,我没有发送或接收函数抛出的错误,只丢失数据或空/部分数据。
以下是代码的一些相关部分。如果需要更多,请告诉我
THX
学家
主设备和从设备之间的流初始化
由主人执行
func InitMPCStream()
{
for Peer in Session.connectedPeers
{
if Peer.displayName != gMasterPeerName
{
let IndexPeer = gtListPlayerMulti.index(where: { $0.Name == Peer.displayName } )
try! gtListPlayerMulti[IndexPeer!].Stream = Session.startStream(withName: "Stream " + Peer.displayName, toPeer: Peer)
gtListPlayerMulti[IndexPeer!].Stream!.delegate = self
gtListPlayerMulti[IndexPeer!].Stream!.schedule(in: RunLoop.main, forMode:RunLoopMode.defaultRunLoopMode)
gtListPlayerMulti[IndexPeer!].Stream!.open()
}
}
}
奴隶执行
func session(_ session: MCSession, didReceive InStream: InputStream, withName StreamName: String, fromPeer PeerID: MCPeerID)
{
InputStream = InStream
InputStream.delegate = self
InputStream.schedule(in: RunLoop.main, forMode: RunLoopMode.defaultRunLoopMode)
InputStream.open()
}
将数据发送到从属设备的功能
此功能在SKScene的更新循环中在主端执行,每次更新几次,所以很频繁。
逻辑是,对于每个更新周期,会发生几个事件(10到100之间)。每个事件都会生成对此函数的调用。发送的数据量不是很重要:3到10行的(String,Any)字典,其中Any可以是字符串,数字(Int,CGFloat ...)或bool。
func SendStreamData(IDPeer: Int = 0, DataToSend: Dictionary<String, Any>)
{
let DataConverted = NSKeyedArchiver.archivedData(withRootObject: DataToSend)
if IDPeer == 0
{
for Peer in Session.connectedPeers
{
let IndexPeer = gtListPlayerMulti.index(where: { $0.Name == Peer.displayName } )
if gtListPlayerMulti[IndexPeer!].Stream!.hasSpaceAvailable
{
let bytesWritten = DataConverted.withUnsafeBytes { gtListPlayerMulti[IndexPeer!].Stream!.write($0, maxLength: DataConverted.count) }
if bytesWritten == -1 { print("Erreur send stream") } else { gSendingNumber = gSendingNumber + 1 }
} else { print("No space in stream") }
}
}
else
{
let IndexPeer = gtListPlayerMulti.index(where: { $0.ID == IDPeer } )
let bytesWritten = DataConverted.withUnsafeBytes { gtListPlayerMulti[IndexPeer!].Stream!.write($0, maxLength: DataConverted.count) }
}
}
从属端收到数据时调用的函数
func stream(_ aStream: Stream, handle eventCode: Stream.Event)
{
switch(eventCode)
{
case Stream.Event.hasBytesAvailable:
gSendingNumber = gSendingNumber + 1
let InputStream = aStream as! InputStream
var Buffer = [UInt8](repeating: 0, count: 1024)
let NumberBytes = InputStream.read(&Buffer, maxLength:1024)
let DataString = NSData(bytes: &Buffer, length: NumberBytes)
if let Message = NSKeyedUnarchiver.unarchiveObject(with: DataString as Data) as? [String:Any] //deserializing the NSData
{ ProcessMPCDataReceived(VCMain: self, PeerID: PeerID, RawData: DataString as Data) }
else { print("Empty Data") }
case Stream.Event.hasSpaceAvailable:
break
case Stream.Event.errorOccurred:
print("ErrorOccurred: \(aStream.streamError?.localizedDescription)")
default:
break
}
}
这里的问题是NSKeyedUnarchiver.unarchiveObject行返回nil,因为DataString不符合预期的字典