RealityKit - SwiftUI के साथ वास्तविकता संगीतकार दृश्य लोड हो रहा है

Aug 17 2020

मैं SwiftUI, RealityKit और ARKit का उपयोग करके चेहरे पर विभिन्न मॉडलों को लोड करने की कोशिश कर रहा हूं।

struct AugmentedRealityView: UIViewRepresentable {

    @Binding var modelName: String

    func makeUIView(context: Context) -> ARView {
    
        let arView = ARView(frame: .zero)
    
        let configuration = ARFaceTrackingConfiguration()

        arView.session.run(configuration, options: [.removeExistingAnchors, 
                                                    .resetTracking])
    
        loadModel(name: modelName, arView: arView)
    
        return arView
    
    }

    func updateUIView(_ uiView: ARView, context: Context) { }

    private func loadModel(name: String, arView: ARView) {

        var cancellable: AnyCancellable? = nil
    
        cancellable = ModelEntity.loadAsync(named: name).sink(
                 receiveCompletion: { loadCompletion in
            
            if case let .failure(error) = loadCompletion {
                print("Unable to load model: \(error.localizedDescription)")
            }                
            cancellable?.cancel()
        },
        receiveValue: { model in
            
            let faceAnchor = AnchorEntity(.face)
            arView.scene.addAnchor(faceAnchor)
            
            faceAnchor.addChild(model)
            
            model.scale = [1, 1, 1]
        })
    }
}

यह है कि मैं उन्हें कैसे लोड करता हूं लेकिन जब कैमरा दृश्य खुलता है और एक मॉडल को लोड करता है तो अन्य मॉडल लोड नहीं होंगे। क्या कोई मेरी मदद कर सकता है?

जवाब

jlsiewert Aug 19 2020 at 21:42

जब आपके Bindingपरिवर्तनों का मूल्य , स्विफ्टयूआई आपके updateUIView(_:,context:)कार्यान्वयन को बुला रहा है, जो ध्यान नहीं देता है।

इसके अतिरिक्त, आप भंडारण नहीं कर रहे हैं AnyCancellable। जब टोकन लौटाया sinkजाता है तो अनुरोध रद्द कर दिया जाता है। जब लेगर मॉडल को लोड करने की कोशिश में अप्रत्याशित विफलता हो सकती है।

इन दोनों समस्याओं को ठीक करने के लिए, का उपयोग करें Coordinator। आयात UIKit आयात RealityKit आयात SwiftUI आयात संयोजन आयात ARKit

struct AugmentedRealityView: UIViewRepresentable {
    class Coordinator {
        private var token: AnyCancellable?
        private var currentModelName: String?
        
        fileprivate func loadModel(_ name: String, into arView: ARView) {
            // Only load model if the name is different from the previous one
            guard name != currentModelName else {
                return
            }
            currentModelName = name
            
            // This is optional
            // When the token gets overwritten
            // the request gets cancelled
            // automatically
            token?.cancel()
            
            token = ModelEntity.loadAsync(named: name).sink(
                receiveCompletion: { loadCompletion in
                    
                    if case let .failure(error) = loadCompletion {
                        print("Unable to load model: \(error.localizedDescription)")
                    }
                },
                receiveValue: { model in
                    
                    let faceAnchor = AnchorEntity(.camera)
                    arView.scene.addAnchor(faceAnchor)
                    
                    faceAnchor.addChild(model)
                    
                    model.scale = [1, 1, 1]
                })
            }
        
        fileprivate func cancelRequest() {
            token?.cancel()
        }
    }
    
    @Binding var modelName: String
    
    func makeCoordinator() -> Coordinator {
        Coordinator()
    }
    
    static func dismantleUIView(_ uiView: ARView, coordinator: Coordinator) {
        coordinator.cancelRequest()
    }
    
    func makeUIView(context: Context) -> ARView {
        
        let arView = ARView(frame: .zero)
        
        let configuration = ARFaceTrackingConfiguration()
        
        arView.session.run(configuration, options: [.removeExistingAnchors,
                                                    .resetTracking])
        
        context.coordinator.loadModel(modelName, into: arView)
        
        return arView
        
    }
    
    func updateUIView(_ uiView: ARView, context: Context) {
        context.coordinator.loadModel(modelName, into: uiView)
    }
}

हम एक नेस्टेड Coordinatorक्लास बनाते हैं जो AnyCancellableटोकन रखता है और loadModelफ़ंक्शन को अंदर ले जाता है Coordinator। एक स्विफ्टयूआई के अलावा View, Coordinatorएक classऐसा जीवन है जब आपका दृश्य दिखाई देता है (हमेशा एक याद है कि स्विफ्टयूआई आपकी इच्छाशक्ति को बना और नष्ट कर सकता है View, इसका जीवनचक्र वास्तविक "दृश्य" से संबंधित नहीं है जो स्क्रीन पर दिखाया गया है)।

बाहर की loadModelकक्षा में हम Bindingदोहराते हैं कि वास्तव में हमारे मूल्य बदल गए हैं ताकि हम उसी मॉडल के लिए चल रहे अनुरोध को रद्द न करें जब SwiftUI हमारे अपडेट करता है View, उदाहरण के लिए पर्यावरण में बदलाव के कारण।

फिर हम makeCoordinatorअपनी Coordinatorवस्तुओं में से एक का निर्माण करने के लिए फ़ंक्शन को लागू करते हैं। दोनों में makeUIViewऔर updateUIViewहम loadModelफ़ंक्शन को अपने फोन पर कहते हैं Coordinator

dimantleUIViewविधि वैकल्पिक है। जब Coordinatorहमारे द्वारा tokenजारी किया गया डिकंस्ट्रक्ट हो जाता है, जो चल रहे अनुरोधों को रद्द करने में कंबाइन को ट्रिगर करेगा।