ARKit – Cannot decode ARAnchor in MCSession
Asked Answered
G

2

6

I'm testing out Apple's Multiuser AR demo app with ARKit 2.0 that was introduced in WWDC 2018: Creating a multiuser AR experience.

The documentation says that after each device relocalizes to the same World Map, only the information needed to recreate each user action is shared among devices (e.g. if the user taps on the screen and a 3D object appears, only that new object's ARAnchor should be sent to other devices). For me, while it shows all the 3D characters that were placed by the sending device before it captured and sent a World Map, it doesn't show any objects that are added after the World Map has been sent. The error I'm getting says:

// can't decode data recieved from peer.

Has anyone had this issue and knows what it's about?

I haven't changed anything in the demo code.

Gunpoint answered 29/8, 2018 at 10:24 Comment(1)
I got a similar issue, sending and receiving ARAnchor. I my case, using the old deprecated Method: "unarchiveTopLevelObjectWithData as ARAnchor?" is working fine. (still in iOS 17) As soon as I use the new "unachivedObject ofClass: ARAnchor.self" I get an Error: The Data couldn't be read because it isn't in the correct format. Sending and receiving a World Map works using both Methods. Just the single ARAnchor will not. Very bizzare...Judie
P
0

I had the same trouble but I kind of solved it in this way.

(1)first create a variable to check if the world map has send.

var worldMapHasInited: Bool = false

(2)Then in func shareSession(_ button: UIButton) add this line to the end below

self.multipeerSession.sendToAllPeers(data)

self.worldMapHasInited = true

(3)And finally in func receivedData(_ data: Data, from peer: MCPeerID)

check if the world map has sent, if is sent, skip checking if the data contains world map or not.

    if !worldMapHasInited {
        if let worldMap = try NSKeyedUnarchiver.unarchivedObject(ofClass: ARWorldMap.self, from: data)
        {
            //....
            // when received world map, set the receiver's 
            // worldMapHasInited to true  
            self.worldMapHasInited = true                                              
        }
    }
    else
        if let anchor = try NSKeyedUnarchiver.unarchivedObject(ofClass: ARAnchor.self, from: data) {
            // ...
    }

This will directly check if the data contains anchor or not.

Pontine answered 24/9, 2018 at 19:49 Comment(0)
L
0

In MultipeerConnectivity ARSession several peers share data among each other. But sent and received data must be, at first, archived and then unarchived using two instance methods of NSKeyedArchiver and NSKeyedUnarchiver classes:

func archive(worldMap: ARWorldMap) throws {

    let data = try NSKeyedArchiver.archivedData(withRootObject: worldMap,
                                         requiringSecureCoding: true)

    try data.write(to: worldMapURL, options: [.atomic])
}

and:

func unarchive(worldMapData: Data) -> ARWorldMap? {

    guard let unarchievedData = try? NSKeyedUnarchiver.unarchivedObject(ofClass: ARWorldMap.self, 
                                                                           from: worldMapData)
    else { return nil }

    return unarchievedData
}

Hence, if you get the following message in Xcode Console:

"can't decode data received from peer"

it means the error occurred while transferring or unarchiving a ARWorldMap data.

Leuko answered 26/6, 2020 at 14:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.