RealityKit–;使用SwiftUI加载Reality Composer场景
我正在尝试使用SwiftUI、RealityKit和ARKit在脸上加载不同的模型RealityKit–;使用SwiftUI加载Reality Composer场景,swiftui,augmented-reality,arkit,realitykit,reality-composer,Swiftui,Augmented Reality,Arkit,Realitykit,Reality Composer,我正在尝试使用SwiftUI、RealityKit和ARKit在脸上加载不同的模型 struct AugmentedRealityView: UIViewRepresentable { @Binding var modelName: String func makeUIView(context: Context) -> ARView { let arView = ARView(frame: .zero) let con
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]
})
}
}
这是我加载它们的方式,但当摄影机视图打开并加载一个模型时,其他模型将不会加载。有人能帮我吗?当您的
绑定的值发生变化时,SwiftUI正在调用您的UpdateUI视图(:,context:)
实现,但它没有任何作用
此外,您没有存储anycancelable
。当sink
返回的令牌被释放时,请求将被取消。当尝试加载较大的模型时,这可能会导致意外的失败
要解决这两个问题,请使用协调器
import UIKit
import RealityKit
import SwiftUI
import Combine
import 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
类,该类保存anycancelable
标记,并将loadModel
函数移动到Coordinator
中。
除了SwiftUI视图
,协调器
是一个类
,它在视图可见时存在(请记住,SwiftUI可能会随意创建和销毁视图
,其生命周期与屏幕上显示的实际“视图”无关)
在outloadModel
类中,我们会仔细检查绑定
的值是否已实际更改,以便在SwiftUI更新视图时(例如,由于环境的变化),我们不会取消对同一模型的持续请求
然后我们实现makeCoordinator
函数来构造一个Coordinator
对象。
在makeUIView
和updateUIView
中,我们在协调器上调用loadModel
函数
import UIKit
import RealityKit
import SwiftUI
import Combine
import 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)
}
}
dimantleUIView
方法是可选的。当协调人被解构时,我们的令牌也会被释放,这将触发合并以取消正在进行的请求。阅读本文了解如何执行此操作: