RealityKit - SwiftUI ile Reality Composer sahnelerini yükleme
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
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.