I should point out that thus far I have no ARView instances; I'm working from the template code provided by Xcode 16.4 which kindly gives me a RealityView:
var body: some View {
ZStack {
RealityView { content in
}
}
}
I'm trying to work out, when a user interaction occurs via say GameController or even a tap on screen, how to decide, when looking directly forward from the current position, how far away the first Entity is.
In SceneKit we have:
func hitTestWithSegment(
from pointA: SCNVector3,
to pointB: SCNVector3,
options: [String : Any]? = nil
) -> [SCNHitTestResult]
But I've been unable to identify how to achieve the same with RealityKit. Perhaps it is time to create an ARView in this game, and use some of the tools there, like:
func entity(at point: CGPoint) -> Entity?
or
func raycast(
from point: CGPoint,
allowing target: ARRaycastQuery.Target,
alignment: ARRaycastQuery.TargetAlignment
) -> [ARRaycastResult]
The "equivalent" of the SCNHitTestResult
object in RealityKit is the CollisionCastHit
object. To get a collection of CollisionCastHit objects, you need to call the raycast(..)
instance method on the RealityKit.Scene object. The ray(..)
method returns an optional tuple containing a pair of SIMD3<Float>
coordinates. For a SceneKit developer, this solution may not seem obvious.
import SwiftUI
import RealityKit
struct ContentView : View {
@State var rvc: RealityViewCameraContent? = nil
let plane = ModelEntity(mesh: .generatePlane(width: 1, height: 1))
init() {
plane.name = "PLANE MODEL"
plane.generateCollisionShapes(recursive: false)
plane.position.z = -1.5
}
var body: some View {
RealityView { content in
// Default camera position is 2.0 meters along +Z axis
self.rvc = content
self.rvc?.add(plane)
}
.onTapGesture {
if let scene = plane.scene, let rvc = self.rvc {
let ray = rvc.ray(
through: .init(x: $0.x, y: $0.y),
in: .local,
to: .scene
)
let castHits: [CollisionCastHit] = scene.raycast(
origin: ray?.origin ?? [],
direction: ray?.direction ?? []
)
if let distance = castHits.first?.distance {
print(plane.name, "is", distance, "away") // 3.5 m. away
} else {
print("nothing")
}
}
}
.background(.black)
}
}
By the way, the implementation of the entity(..)
method will look like this:
let entity = self.rvc?.entity(
at: .init(x: $0.x, y: $0.y),
in: .local
)
print(entity?.name ?? "nil", "–", entity?.position ?? [])