Collisions & Physics: Collision Modes Are Mysterious, but Are They Important?
Exploring Triggers and Rigid Bodies in RealityKit.
Overview
One of the first things you’ll notice when you add a Collision component in Reality Composer Pro is the property called Mode. It has two options:
- Default
- Trigger
Let’s talk about a couple of examples.
- We can add a collision component with a default mode, then add a Physics Body component. This entity can be used with the three use cases we talked about recently. It can respond to other physical entities, fire collision events, and be used for input.
- We can add only a collision component, then set the mode to Trigger. This entity will fire events when it collides with other entities (regardless of their mode). It can also be used for input.
We can use the Default mode for physics (with a Physics Body) and the Trigger mode when we don’t need physics. Makes sense, right?
Well, not really. I saw this caveat in the docs from Apple:
RealityKit ignores an entity’s collision component mode if the entity also has a
PhysicsBodyComponent. An entity can be a rigid body, or a trigger, but not both at the same time.
So what really determines the collision mode is the presence of the Physics Body Component? That seems to be the case.
Given example 1 above, the collision mode value is always ignored because we added a physics body.
Given example 2 above, we can change the mode from Trigger to Default and still get the same behavior. So why bother to set the mode to Trigger? It’s possible that visionOS has some sort of optimization in place when we select Trigger. It can also be helpful when working with entities to quickly see which ones are triggers.
Video Demo
Example Code
Entity Setup:


struct Example058: View {
@State var lastCollision = "none"
@State var collisionEventExample: EventSubscription?
var body: some View {
RealityView { content in
// Load the scene and position it in the volume
guard let scene = try? await Entity(named: "CollisionModes", in: realityKitContentBundle) else { return }
content.add(scene)
scene.setScale(.init(repeating: 0.8), relativeTo: nil)
scene.position.y = -0.4
// Let's add a collision event to the red sphere. We'll capture the name of the other entity we collide with
if let subject = scene.findEntity(named: "ExampleInput") {
collisionEventExample = content
.subscribe(to: CollisionEvents.Began.self, on: subject) { event in
lastCollision = event.entityB.name
}
}
}
.ornament(attachmentAnchor: .scene(.back), ornament: {
VStack() {
Text("Last Collision:")
Text(lastCollision)
}
.font(.extraLargeTitle)
.padding()
.frame(width: 460, height: 200)
.glassBackgroundEffect()
})
.modifier(DragGestureImproved())
}
}Does anyone else think this is weird?
Download the Xcode project with this and many more examples from Step Into Vision.
Some examples are provided as standalone Xcode projects. You can find those here.

Follow Step Into Vision