Hello @mlbonniec , thank you for your question!
I believe what you are looking for is raycast(from:to:query:mask:relativeTo:).
You can perform a raycast on the Scene that an Entity belongs to.
If you configure an entity with ManipulationComponent, you can subscribe to the event ManipulationEvents.WillRelease to execute code when a person releases an object.
Then, you can perform a raycast on the scene downward from the entity's position and place the entity on the closest surface.
Here's a quick implementation I threw together demonstrating how to position an Entity on raycast hit:
// This code runs when a person releases an object.
func handleManipulationWillRelease(event: ManipulationEvents.WillRelease) {
// Start the raycast from the position of the entity when it is released.
let raycastStart = event.entity.position
// End the raycast one meter below the starting point (surfaces further away than 1m will be ignored).
let raycastEnd = raycastStart + [0, -1, 0]
// Perform the raycast and return an optional array of CollisionCastHit
guard let hits = event.entity.scene?.raycast(from: raycastStart, to: raycastEnd) else {
return
}
// Get the closest hit.
guard let closestHit = hits.min(by: { $0.distance < $1.distance }) else {
return
}
// Use an animation to make the placement less abrupt (optional).
Entity.animate(.default) {
// Place the entity at the hit position and orient it along the hit normal.
event.entity.position = closestHit.position
event.entity.orientation = simd_quatf(angle: 0, axis: closestHit.normal)
}
}
Note that you're asking for "closest" surface and the above code only looks directly below the entity to find a point to snap to, so it will miss closer surfaces above and to the side of the entity that don't intersect with a ray pointing directly down.
Depending on your use case, consider using convexCast with a sphere shape centered around the entity to find the closest surface in any direction.
Let me know if that helps!