How to detect whether two entities collide in RealityView and execute some instructions after the collision. It is assumed that both entities have collision components, and one of them also has an anchor component (such as a binding hand).
Hi @lijiaxu
You can detect collisions by subscribing to collision events on an entity. For example, if you have an entity with a collision component, myEntity
, you can subscribe to its various collision events like so:
@State private var collisionBegan: EventSubscription?
@State private var collisionUpdated: EventSubscription?
@State private var collisionEnded: EventSubscription?
var body: some View {
RealityView { content in
// Create myEntity here.
...
// Subscribe to collision events.
collisionBegan = content.subscribe(to: CollisionEvents.Began.self, on: myEntity) { collisionEvent in
print("Collision began.")
}
collisionUpdated = content.subscribe(to: CollisionEvents.Updated.self, on: myEntity) { collisionEvent in
print("Collision updated.")
}
collisionEnded = content.subscribe(to: CollisionEvents.Ended.self, on: myEntity) { collisionEvent in
print("Collision ended.")
}
}
}
In this case, I call a print statement when the collision occurs, but you can execute whatever instructions you like in the collision event callback.
Things get a little bit more complicated when an entity with an AnchoringComponent
is involved, as you will need to set its physicsSimulation
property to .none
, as well as start a SpatialTrackingSession
. Here's a snippet that demonstrates how to do that:
@State private var collisionBegan: EventSubscription?
@State private var collisionUpdated: EventSubscription?
@State private var collisionEnded: EventSubscription?
var body: some View {
RealityView { content in
// Start a spatial tracking session for the hands.
let configuration = SpatialTrackingSession.Configuration(tracking: [.hand])
let session = SpatialTrackingSession()
await session.run(configuration)
// Create a cube with collision.
let collidableCube = ModelEntity(mesh: .generateBox(size: 0.2), materials: [SimpleMaterial(color: .green.withAlphaComponent(0.75), isMetallic: false)])
collidableCube.position = [0, 1, -0.5]
collidableCube.generateCollisionShapes(recursive: false)
content.add(collidableCube)
// Create an anchor entity with collision tracking the right index finger tip.
let rightIndexTipAnchor = AnchorEntity(.hand(.right, location: .indexFingerTip))
rightIndexTipAnchor.anchoring.physicsSimulation = .none
rightIndexTipAnchor.components.set(ModelComponent(mesh: .generateSphere(radius: 0.01), materials: [SimpleMaterial()]))
rightIndexTipAnchor.components.set(CollisionComponent(shapes: [.generateSphere(radius: 0.01)]))
content.add(rightIndexTipAnchor)
// Subscribe to collision events.
collisionBegan = content.subscribe(to: CollisionEvents.Began.self, on: rightIndexTipAnchor) { collisionEvent in
print("Collision began.")
}
collisionUpdated = content.subscribe(to: CollisionEvents.Updated.self, on: rightIndexTipAnchor) { collisionEvent in
print("Collision updated.")
}
collisionEnded = content.subscribe(to: CollisionEvents.Ended.self, on: rightIndexTipAnchor) { collisionEvent in
print("Collision ended.")
}
}
}
For this approach, be sure to add an entry for NSHandsTrackingUsageDescription
to your app’s information property list to provide a usage description that explains how your app uses the hand tracking information.