RealityKit Custom ARAnchor not syncing across devices

279 views Asked by At

I'm using Apple's custom ARAnchor in a config.isCollaborationEnabled = true environment.

When I call the following on DeviceA:

let boardAnchor = BoardAnchor(transform: last.worldTransform, size: CGSize(width: 10, height: 11))
arView.session.add(anchor: boardAnchor)

I can see the delegate func session(_ session: ARSession, didAdd anchors: [ARAnchor]) get called with the BoardAnchor on DeviceA.

However, DeviceB does not receive such a delegate call.

If however I add a non-subclassed ARAnchor on DeviceA, I can see the delegate called on DeviceB.

let namedAnchor = ARAnchor(name: "test", transform: last.worldTransform)
arView.session.add(anchor: namedAnchor)

So I'm really confused as to why the subclass doesn't work...any ideas?

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")
}
}

Delegate

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
      }

    }
  
}
2

There are 2 answers

1
YanivH On

I think that other than simply noting the config.isCollaborationEnabled = true, you need to manually handle the data sent out and the connectivity and other peers.

In addition, there is a different delegate method to get the collaborated anchors, if I remember correctly.

Please note the following: https://developer.apple.com/documentation/arkit/creating_a_collaborative_session

There is a sample project there that will probably answer most of your questions..

1
ZbadhabitZ On

I believe this line from the Building Collaborative AR Experiences session (WWDC 2019) might explain the issue you're facing;

Last, only the user created ARAnchors are shared. That excludes all the subclass ARAnchors, including ARImageAnchor, ARPlaneAnchor, and ARObjectAnchor. That also excludes the user subclass ARAnchor which were used to attach user data within Map Save and Load.

The session seems to go on to indicate that in lieu of using a sublcassed ARAnchor, you can define your own Entity component and conform your Entity to that protocol, hereby allowing you to negate having to use a subclassed ARAnchor and allowing the component, which would synchronize across the session, to perform a similar task. However, if you are not using RealityKit, and are, instead, using SceneKit or SpriteKit, you will likely need to determine a different methodology, such as avoiding subclassing ARAnchor and move your logic in BoardAnchor somewhere else.