Происходит следующее: когда якорь изображения выходит из поля зрения, AnchorEntity становится незакрепленным, а RealityKit прекращает его рендеринг и всех его потомков.
Одним из способов обойти это может быть простое отделение вашегопривязка изображения и контент, который вы хотите визуализировать, добавьте привязку изображения вручную в коде, а затем, когда привязка изображения будет впервые обнаружена, добавьте содержимое в сцену под другой привязкой мира. Когда преобразование привязки изображения обновляется, обновите привязку мира, чтобы соответствовать.
Таким образом, вы можете использовать привязку изображения, когда она видна, чтобы получить последнее преобразование, но когда она исчезает, рендеринг контента непривязан к этому. Примерно так, как показано ниже (вам нужно создать ресурсную группу AR с именем ARTest и добавить к ней изображение с именем «test», чтобы привязка заработала):
import ARKit
import SwiftUI
import RealityKit
import Combine
struct ContentView : View {
var body: some View {
return ARViewContainer().edgesIgnoringSafeArea(.all)
}
}
let arDelegate = SessionDelegate()
struct ARViewContainer: UIViewRepresentable {
func makeUIView(context: Context) -> ARView {
let arView = ARView(frame: .zero)
arDelegate.set(arView: arView)
arView.session.delegate = arDelegate
// Create an image anchor, add it to the scene. We won't add any
// rendering content to the anchor, it will be used only for detection
let imageAnchor = AnchorEntity(.image(group: "ARTest", name: "test"))
arView.scene.anchors.append(imageAnchor)
return arView
}
func updateUIView(_ uiView: ARView, context: Context) {}
}
final class SessionDelegate: NSObject, ARSessionDelegate {
var arView: ARView!
var rootAnchor: AnchorEntity?
func set(arView: ARView) {
self.arView = arView
}
func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {
// If we already added the content to render, ignore
if rootAnchor != nil {
return
}
// Make sure we are adding to an image anchor. Assuming only
// one image anchor in the scene for brevity.
guard anchors[0] is ARImageAnchor else {
return
}
// Create the entity to render, could load from your experience file here
// this will render at the center of the matched image
rootAnchor = AnchorEntity(world: [0,0,0])
let ball = ModelEntity(
mesh: MeshResource.generateBox(size: 0.01),
materials: [SimpleMaterial(color: .red, isMetallic: false)]
)
rootAnchor!.addChild(ball)
// Just add another model to show how it remains in the scene even
// when the tracking image is out of view.
let ball2 = ModelEntity(
mesh: MeshResource.generateBox(size: 0.10),
materials: [SimpleMaterial(color: .orange, isMetallic: false)]
)
ball.addChild(ball2)
ball2.position = [0, 0, 1]
arView.scene.addAnchor(rootAnchor!)
}
func session(_ session: ARSession, didUpdate anchors: [ARAnchor]) {
guard let rootAnchor = rootAnchor else {
return
}
// Code is assuming you only have one image anchor for brevity
guard let imageAnchor = anchors[0] as? ARImageAnchor else {
return
}
if !imageAnchor.isTracked {
return
}
// Update our fixed anchor to image transform
rootAnchor.transform = Transform(matrix: imageAnchor.transform)
}
}
#if DEBUG
struct ContentView_Previews : PreviewProvider {
static var previews: some View {
ContentView()
}
}
#endif
ПРИМЕЧАНИЕ. Это выглядит как преобразование дляARImageAnchor часто обновляется при перемещении, когда ARKit пытается вычислить точную плоскость изображения (контент может показаться, что он находится в нужном месте, но, например, значение z не является точным), убедитесь, что размеры вашего изображения точны в ARгруппа ресурсов для изображения, чтобы лучше отслеживать.