RealityKit - SwiftUI ile Reality Composer sahnelerini yükleme

Aug 17 2020

SwiftUI, RealityKit ve ARKit kullanarak yüze farklı modeller yüklemeye çalışıyorum.

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

Bunları böyle yüklüyorum ancak kamera görünümü açılıp bir modeli yüklediğinde diğer modeller yüklenmeyecek. Biri bana yardım edebilir mi?

Yanıtlar

jlsiewert Aug 19 2020 at 21:42

BindingDeğişikliklerinizin değeri ne zaman , SwiftUI updateUIView(_:,context:)uygulamanızı çağırıyor , ki bu farketmez .

Ek olarak AnyCancellable,. Tarafından döndürülen jetonun sinkayrılması kaldırıldığında, istek iptal edilecektir. Bu, lager modellerini yüklemeye çalışırken beklenmeyen arızalara neden olabilir.

Bu sorunların her ikisini de düzeltmek için, bir Coordinator. UIKit içe aktarma RealityKit içe aktarma SwiftUI içe aktarma İçe aktarma ARKit'i birleştir

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

Simgeyi Coordinatortutan AnyCancellableve loadModelişlevi Coordinator. Bir SwiftUI dışında View, Coordinatorbir olduğunu classgörüşünüz görünür yaşarken (her zaman SwiftUI oluşturmak ve sizin imha olabileceğini unutmayın Viewiradesiyle, kendi yaşam döngüsü ekranda gösterilen gerçek "görünüm" ilgili değildir).

Derste , SwiftUI bizi güncellediğinde , örneğin ortamdaki bir değişiklik nedeniyle , aynı model için devam eden bir talebi iptal etmememiz için , sınıfımızın loadModeldeğerinin Bindinggerçekten değiştiğini iki kez kontrol ederiz View.

Ardından makeCoordinator, Coordinatornesnelerimizden birini oluşturmak için işlevi uygularız . Hem de makeUIViewve de updateUIViewdediğimiz loadModelsayfamızda yer fonksiyonunu Coordinator.

dimantleUIViewYöntem, isteğe bağlıdır. Ne zaman Coordinatordeconstructed alır bizim tokensüregelen isteklerini iptal içine birleştirin tetikleyecek olan sıra serbest bırakılır.