RealityKit - SwiftUI के साथ वास्तविकता संगीतकार दृश्य लोड हो रहा है
मैं 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]
})
}
}
यह है कि मैं उन्हें कैसे लोड करता हूं लेकिन जब कैमरा दृश्य खुलता है और एक मॉडल को लोड करता है तो अन्य मॉडल लोड नहीं होंगे। क्या कोई मेरी मदद कर सकता है?
जवाब
जब आपके 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
जारी किया गया डिकंस्ट्रक्ट हो जाता है, जो चल रहे अनुरोधों को रद्द करने में कंबाइन को ट्रिगर करेगा।