我在
config.isCollaborationEnabled = true
环境中使用 Apple 的自定义 ARAnchor。
当我在DeviceA上调用以下命令时:
let boardAnchor = BoardAnchor(transform: last.worldTransform, size: CGSize(width: 10, height: 11))
arView.session.add(anchor: boardAnchor)
我可以看到委托
func session(_ session: ARSession, didAdd anchors: [ARAnchor])
被DeviceA上的BoardAnchor调用。
但是,DeviceB 没有收到这样的委托呼叫。
但是,如果我在 DeviceA 上添加非子类 ARAnchor,我可以看到在 DeviceB 上调用的委托。
let namedAnchor = ARAnchor(name: "test", transform: last.worldTransform)
arView.session.add(anchor: namedAnchor)
所以我真的很困惑为什么子类不起作用......有什么想法吗?
class BoardAnchor: ARAnchor {
let size: CGSize
init(transform: float4x4, size: CGSize) {
self.size = size
super.init(name: "Board", transform: transform)
}
override class var supportsSecureCoding: Bool {
return true
}
required init?(coder aDecoder: NSCoder) {
self.size = aDecoder.decodeCGSize(forKey: "size")
super.init(coder: aDecoder)
}
// this is guaranteed to be called with something of the same class
required init(anchor: ARAnchor) {
let other = anchor as! BoardAnchor
self.size = other.size
super.init(anchor: other)
}
override func encode(with aCoder: NSCoder) {
super.encode(with: aCoder)
aCoder.encode(size, forKey: "size")
}
}
代表
func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {
for anchor in anchors {
DLog("didAdd anchor: \(anchor)")
if anchor.name == "test" {
// Non-sublcass ARAnchor ok
}
if let board = anchor as? BoardAnchor {
// Never called
}
}
}
我相信“构建协作 AR 体验”会议(WWDC 2019)中的这句话可能可以解释您面临的问题;
最后,仅共享用户创建的 ARAnchor。这排除了所有 ARAnchors 子类,包括 ARImageAnchor、ARPlaneAnchor 和 ARObjectAnchor。这也排除了用户子类 ARAnchor 用于在地图保存和加载中附加用户数据。会议似乎继续表明,代替使用子类 ARAnchor,您可以定义自己的实体组件并使您的实体符合该协议,从而允许您不必使用子类 ARAnchor 并允许该组件,这将跨会话同步,以执行类似的任务。 但是,如果您不使用 RealityKit,而是使用 SceneKit 或 SpriteKit,您可能需要确定不同的方法,例如避免子类化 ARAnchor 并将逻辑移至其他地方。
我认为除了简单地注意到
BoardAnchor
- 要保存在 ARWorldMap 中(我想也在跨设备同步中),您需要确保您的类实现
config.isCollaborationEnabled = true
和 ARAnchorCopying
协议。