Search code examples
iosswiftarkitrealitykit

RealityKit – ARView raycasting returns 0 results


I have a subclass of RealityKit's ARView that has the following function for making a Raycast:

func makeRaycastQuery(alignmentType: ARRaycastQuery.TargetAlignment) -> simd_float4x4? {
    let results = self.raycast(from: self.center,
                           // Better for pinning to planes
                           allowing: .estimatedPlane,
                          alignment: alignmentType)

    // We don't care about changing scale on raycast so keep it the same
    guard var result = results.first?.worldTransform else { return nil }
    result.scale = SCNVector3(1, 1, 1)
    return result
}

However, my results array is always empty. Is there some sort of other configuration I need to do when setting up an ARView to enable raycasting?


Solution

  • Try this code (I've written it for iPad's Playgrounds):

    import RealityKit
    import SwiftUI
    import ARKit
    import PlaygroundSupport
    
    struct ContentView : View {
        
        @State private var arView = ARView(frame: .zero)
        
        var body: some View {
            return ARContainer(arView: $arView)
                .gesture(
                    TapGesture()
                        .onEnded { _ in
                            raycasting(arView: arView)
                        }
                )
        }        
        func raycasting(arView: ARView) {
            guard let query = arView.makeRaycastQuery(from: arView.center, 
                                                  allowing: .estimatedPlane, 
                                                 alignment: .any)
            else { fatalError() }
                
            guard let result = arView.session.raycast(query).first
            else { fatalError() }
                
            let entity = ModelEntity(mesh: .generateSphere(radius: 0.1))
            let anchor = AnchorEntity(raycastResult: result)
            anchor.addChild(entity)
            arView.scene.anchors.append(anchor)
        }
    }
    

    struct ARContainer : UIViewRepresentable {
        
        @Binding var arView: ARView
        
        func makeUIView(context: Context) -> ARView {
            arView.cameraMode = .ar
            return arView
        }   
        func updateUIView(_ view: ARView, context: Context) { }
    }
    

    PlaygroundPage.current.needsIndefiniteExecution = true
    PlaygroundPage.current.setLiveView(ContentView())
    

    P. S.

    This version works in UIKit app.