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
Binding
Değ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 sink
ayrı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 Coordinator
tutan AnyCancellable
ve loadModel
işlevi Coordinator
. Bir SwiftUI dışında View
, Coordinator
bir olduğunu class
görüşünüz görünür yaşarken (her zaman SwiftUI oluşturmak ve sizin imha olabileceğini unutmayın View
iradesiyle, 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 loadModel
değerinin Binding
gerçekten değiştiğini iki kez kontrol ederiz View
.
Ardından makeCoordinator
, Coordinator
nesnelerimizden birini oluşturmak için işlevi uygularız . Hem de makeUIView
ve de updateUIView
dediğimiz loadModel
sayfamızda yer fonksiyonunu Coordinator
.
dimantleUIView
Yöntem, isteğe bağlıdır. Ne zaman Coordinator
deconstructed alır bizim token
süregelen isteklerini iptal içine birleştirin tetikleyecek olan sıra serbest bırakılır.