В настоящее время я успешно делюсь картой мира AR по сеансу множителя и пытаюсь отправить отдельные данные снаряда (положение, угол, скорость, тип) по сети от обоих одноранговых клиентов, но я не совсем уверенкак сериализовать эти типы данных SCNVector3, используя Codable, и при этом я не могу найти какую-либо документацию по этому поводу ... именно поэтому я здесь.Мне нужно иметь возможность разархивировать данные следующим методом
let shouldSend = MovementData(velocity: data.velocity, angular: Float(data.angular), position: posStr , x:Float(data.x), y:Float(data.y),z:Float(data.z),type:"Striker")
guard let sendData = try? NSKeyedArchiver.archivedData(withRootObject: shouldSend, requiringSecureCoding: true)
else { fatalError("can't encode movementData") }
Я пытаюсь использовать следующее для кодирования данных
import SceneKit
open class MovementData: NSObject, NSSecureCoding {
public static var supportsSecureCoding: Bool = true
var velocity = CGPoint.zero,
angular = Float(0),
position:String = "SCNVector3(x:0,y:0.5,z:0)",
orientation = SCNVector3(),
x = Float(0),
y = Float(0),
z = Float(0),
type = String()
enum Key:String {
case velocity = "velocity"
case angular = "angular"
case position = "position"
case x = "x"
case y = "y"
case z = "z"
case type = "type"
}
public func encode(with aCoder: NSCoder) {
aCoder.encode(velocity as CGPoint, forKey: Key.velocity.rawValue)
aCoder.encode(angular as Float, forKey: Key.angular.rawValue)
aCoder.encode(position as String, forKey: Key.position.rawValue)
aCoder.encode(x as Float, forKey: Key.x.rawValue)
aCoder.encode(y as Float, forKey: Key.y.rawValue)
aCoder.encode(z as Float, forKey: Key.z.rawValue)
aCoder.encode(type as String, forKey: Key.type.rawValue)
}
public convenience required init?(coder aDecoder: NSCoder) {
let _velocity = aDecoder.decodeCGPoint(forKey: Key.velocity.rawValue)
let _angular = aDecoder.decodeFloat(forKey: Key.angular.rawValue)
let _position = aDecoder.decodeObject(forKey: Key.position.rawValue)
let _x = aDecoder.decodeFloat(forKey: Key.x.rawValue)
let _y = aDecoder.decodeFloat(forKey: Key.y.rawValue)
let _z = aDecoder.decodeFloat(forKey: Key.z.rawValue)
let _type = aDecoder.decodeObject(forKey: Key.type.rawValue)
self.init(velocity: _velocity, angular: _angular, position: _position as! String, x:_x,y:_y,z:_z,type:_type as! String)
}
init(velocity: CGPoint, angular: Float, position:String, x:Float,y:Float,z:Float,type:String) {
self.velocity = velocity
self.angular = angular
self.position = position
self.x = x
self.y = y
self.z = z
self.type = type
}}
Я использую следующую модель
//
// Striker.swift
import Foundation
import SceneKit
public struct StrikerData: CustomStringConvertible {
var velocity = CGPoint.zero,
angular = CGFloat(0),
// position = SCNVector3()
x = CGFloat(0),
y = CGFloat(0.5),
z = CGFloat(0)
mutating func reset() {
velocity = CGPoint.zero
angular = 0
x = 0
y = 0.5
z = 0
}
public var description: String {
return "StrikerData(velocity: \(velocity), angular: \(angular), position: SCNVector3(x:\(x),y:\(y),z:\(z)))"
}
}
struct Striker {
var name: String
var x: String
var y: String
var z: String
var orientation: String
var velocity:String
init(name: String, orientation: String, velocity: String,x: String, y: String,z:String) {
self.name = name
self.orientation = orientation
self.velocity = velocity
self.x = x
self.y = y
self.z = z
}
}
//MARK: - OpponentStriker
open class OpponentStriker: SCNView {
var striker: Striker!
var trackingHandler: ((StrikerData) -> ())?
var beginHandler: (() -> Void)?
var stopHandler: (() -> Void)?
var substrate: OpponentStriker!
private var tracking = false
private(set) var data = StrikerData()
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
@objc func listen() {
if tracking {
trackingHandler?(data)
}
}
//MARK: - Overrides
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first{
let striker = touch.location(in: self)
tracking = true
beginHandler?()
}
}
open override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch: AnyObject in touches {
let location = touch.location(in: self)
guard tracking else {
return
}
print("Stopped here FIX THIS!!!!!!")
}
}
open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
resetStriker()
}
open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
resetStriker()
}
// CustomStringConvertible protocol
open override var description: String {
return "OpponentStriker(data: \(data))"
print("OpponentStriker(data:\(data)")
}
// private methods
private func resetStriker() {
tracking = false
let moveToBack = SCNAction.move(to: SCNVector3(x:0, y:1, z: 0), duration: TimeInterval(0.1))
moveToBack.timingMode = .easeOut
data.reset()
stopHandler?();
}
}
typealias ? = OpponentStriker
Затем я отправляю данные из контроллера представления при создании узла со следующей функцией:
guard let tableScene = SCNScene(named: "art.scnassets/table.scn"),
let strikerOne = tableScene.rootNode.childNode(withName: "Striker", recursively: false)
// let strikerTwo = tableScene.rootNode.childNode(withName: "Striker", recursively: false)
else { print("Cant find strikerOne node")
return
}
let nodeScale = SCNVector3(0.5,1.25,0.75)
strikerOne.position = SCNVector3(x,y,z)
strikerOne.physicsBody = SCNPhysicsBody(type: .kinematic , shape: SCNPhysicsShape(node: strikerOne, options: [SCNPhysicsShape.Option.scale: nodeScale]))
strikerOne.physicsBody?.categoryBitMask = BitMaskCategory.striker.rawValue
strikerOne.physicsBody?.contactTestBitMask = BitMaskCategory.puck.rawValue
self.strikerOneNode = strikerOne
if player == "One" {
self.selectedNode = strikerOne
}
self.sceneView.scene.rootNode.addChildNode(strikerOne)
let mat4 = strikerOne.transform
let f4x4 = simd_float4x4(mat4)
let anchor = ARAnchor(name: "StrikerOne", transform: f4x4 )
sceneView.session.add(anchor: anchor)
// Send the anchor info to peers, so they can place the same content.
guard let data = try? NSKeyedArchiver.archivedData(withRootObject: anchor, requiringSecureCoding: true)
else { fatalError("can't encode anchor") }
self.multipeerSession.sendToAllPeers(data)
print("Striker One added")
// guard let data = try? NSKeyedArchiver.archivedData(withRootObject: strikerOne, requiringSecureCoding: true)
self.sceneView.scene.rootNode.addChildNode(strikerTwo)
и пытаюсь десериализовать данные, используя NSKeyedUnarchiver
if let movement = try NSKeyedUnarchiver.unarchivedObject(ofClass:MovementData.self, from: data) {
print(" movement DATA FROM \(peer) with data \(data)")
print(movement)
}
Я получаю сообщение об ошибке:
can't decode data recieved from <MCPeerID: 0x28294b120 DisplayName = Montreaux’s iPhone>
Я использую следующую демонстрационную версию / файл Readme для создания многопользовательского режима AR:
Демо-версия Apple ARKit MultiUser
Вся помощь очень ценится,
Приветствия!