RealityKit Multipeer Session - Object Sync Issue

久未见 提交于 2020-05-30 07:59:39

问题


I can’t figure out the common objects of 3D models for multipeer sessions (with their synchronization).

Design: Users of the application can enter a multipeer session, place objects on the stage, while other peers can see these models, their transformations, interact with these objects themselves and place their own - while also maintaining the ability to interact with their objects to other peers of the session.

Questions I have encountered:

  1. How to publish one instance of a model for one object (now when you publish two copies of each model are obtained - one instance of a model for peer A, which peer B cannot interact with, and one instance of a model for peer B, with which peer A cannot interact).

UPDATE: This issue was resolved by adding in the session (_ session :, didAdd anchors:) code block (modeled on WWDC 2019 - 610):

// Use session identifier to determine creator of the ARAnchor
// Self-placed ARanchor
if anchor.sessionIdentifier == session.identifier {
   // ...
// ARAnchor from another participant
} else {
   // ...
}

Now func correctly separates addition of its anchors from those added by other participants.

In addition, when loading, for example, modelA, with peer A, in order to use this model in a multipeer session, you need to not only load it in ModelEntity.loadAsync (contentsOf :) method, but give a unique multipeer session name via ModelEntity.loadAsync (contentsOf :, withName :) - then at peer B in session (_ session: ARSession, didAdd anchors: [ARAnchor]) you get model name (for example, modelA) from name of such ARAnchor (when created on peer A, it should be named - for example, anchor_modelA), you also load as an asset through ModelEntity.loadAsync (contentsOf :, withName: "modelA") - in contentsOf: specify the URL of the locally stored model file, after which modelA correctly displayed at the peer B, and in the placement of the duplicate does not occur.

  1. When changing some settings, I get only a wireframe for peer В (AnchorEntity + Collision + Gestures for Entity, where Entity itself with the loaded model is missing) - this option in some sense works, since only one instance gets onto the scene , and peer A (author) can interact with him (peer B cannot), but still this is an unsatisfactory result.

UPDATE: Answer in paragraph 1

  1. How to dynamically transfer and obtain Entity rights (when peer B can work with peer A model and vice versa)?

Scenario:

  1. I tap on the screen to save simd_float4x4 for the future ARAnchor, select the model file from the local file directory, and return.

  2. By simd_float4x4 I form ARAnchor:

    /// Creates and adds in ARSession new ARAnchor.
    /// - Parameter modelName: Name of placed model to form name of ARAnchor.
    func placeAnchor(with modelName: String) {

        defer {
            tempSimd_float4x4 = nil
        }

        guard let worldPosition = tempSimd_float4x4 else { fatalError()}
        let anchor = ARAnchor(name: "\(SettingsApp.anchorARSessionPrefix)\(modelName)", transform: worldPosition)

        arView.session.add(anchor: anchor)
    }

  1. In method session (_ session: ARSession, didAdd anchors: [ARAnchor]), after adding ARAnchor, it is validated by name and function is called
    /// Adds model to scene of ARView.
    /// - Parameters:
    ///   - anchor: Anchor for AnchorEntity binding.
    ///   - modelName: Name of added model.
    ///   - modelLocalUrl: URL of  added model.
    /// - Throws: Function can throw exceptions.
    func placeEntity(for anchor: ARAnchor, modelName: String, modelLocalUrl: URL?) throws {

        defer {
            keychainSwift.delete(KeychainSwiftKeys.placingModelURL.rawValue)
        }

        var modelURL: URL?
        if modelLocalUrl == nil {
            if let modelUrlKeychainString = keychainSwift.get(KeychainSwiftKeys.placingModelURL.rawValue),
                let modelUrlKeychainURL = URL(string: modelUrlKeychainString) {
                modelURL = modelUrlKeychainURL
            } else {
                fatalError()
            }
        } else {
            modelURL = modelLocalUrl
        }

        do {

            let modelEntity = try Entity.loadModel(contentsOf: modelURL!, withName: "\(SettingsApp.modelEntityARSessionPrefix)\(String(modelName))")
            modelEntity.name = "\(SettingsApp.modelEntityARSessionPrefix)\(modelName)"
            modelEntity.generateCollisionShapes(recursive: true)

            let anchorEntity = AnchorEntity(anchor: anchor)
            anchorEntity.name = "\(SettingsApp.anchorEntityARSessionPrefix)\(modelName)"
            anchorEntity.addChild(modelEntity)

            arView.scene.addAnchor(anchorEntity)

            arView.installGestures(for: modelEntity)

            playAnimation(for: modelEntity)

        } catch {
            fatalError(error.localizedDescription)
        }
    }

Accordingly, when transferring Collaboration Data, peer B calls session (_ session: ARSession, didAdd anchors: [ARAnchor]), ARAnchor validates by name and also calls placeEntity (for anchor :, modelName :, modelLocalUrl :?) throws.

The multipeer session is configured as shown here: https://github.com/AddedLayer/multipeer-session

I will accept any help with thanks, thank you in advance for the answers! Have a nice code!

来源:https://stackoverflow.com/questions/61839870/realitykit-multipeer-session-object-sync-issue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!