RealityKit Basics: Working with Events
Our apps can respond to a number of scene and component events.
Setting up an Event Subscription
In the article covering RealityViewContent we saw that an important feature it provides is access to Events. We can subscribe to a number of events that occur throughout RealityKit. We call content.subscribe with the event we want. Then we provide a closure with the code to execute when the event fires.
_ = content.subscribe(to: ManipulationEvents.WillBegin.self) { event in
print("picked up \(event.entity.name)")
}We can improve this by keeping track of the EventSubscription in our view.
@State private var willBegin: EventSubscription?Then we can assign the subscription to this variable.
willBegin = content.subscribe(to: ManipulationEvents.WillBegin.self) { event in
print("picked up \(event.entity.name)")
}The main reason we do this is to provide ourselves with access to the subscription. We can cancel and reset it if needed. It also helps to cancel and clean up these events with the host view will disappear.
.onDisappear() {
willBegin?.cancel() // cancel the subscription
willBegin = nil // nil out the var so we no longer have a reference to the subscription
willRelease?.cancel()
willRelease = nil
}Notable RealityKit Events
Some common event sets include
- SceneEvents: Events for when entities are added or removed, activated or deactivated. We can also watch hierarchy changes. There is even an
updateevent from which we can read delta time†- ComponentEvents: Events raise for adding, removing, activating or deactivating components.
- CollisionEvents: These events are specific to the Collision features in RealityKit.
- ManipulationEvents: Convenient events for working with Manipulation Component.
†if you find yourself using delta time in RealityKit, then should probably be working in a custom system…
This Scene Event will print when we add an entity to the scene.
sceneEventExample = content.subscribe(to: SceneEvents.DidAddEntity.self) { event in
print("entity added to the scene! \(event.entity.name)")
}While this Component Event will print for each component we add to the entity.
componentEventExample = content.subscribe(to: ComponentEvents.DidAdd.self) { event in
print("component \(event.componentType) added to \(event.entity.name)")
}Our entity gets created with three default components. The others are added when we call configureEntity
entity added to the scene! subjectA
component Transform added to subjectA
component SynchronizationComponent added to subjectA
component ModelComponent added to subjectA
component InputTargetComponent added to subjectA
component CollisionComponent added to subjectA
component HoverEffectComponent added to subjectA
component ManipulationComponent added to subjectASee also:
Full Example Code
struct Example107: View {
@State private var sceneEventExample: EventSubscription?
@State private var componentEventExample: EventSubscription?
@State private var willBegin: EventSubscription?
@State private var willRelease: EventSubscription?
@State private var collisionBeganUnfiltered: EventSubscription?
var body: some View {
RealityView { content in
// Scene Event Example
sceneEventExample = content.subscribe(to: SceneEvents.DidAddEntity.self) { event in
print("entity added to the scene! \(event.entity.name)")
}
// Component Event Example
componentEventExample = content.subscribe(to: ComponentEvents.DidAdd.self) { event in
print("component \(event.componentType) added to \(event.entity.name)")
}
let subjectA = createStepDemoBox()
subjectA.name = "subjectA"
subjectA.position.x = 0.15
ManipulationComponent.configureEntity(subjectA, collisionShapes: [.generateBox(size: .init(repeating: 0.25))])
content.add(subjectA)
let subjectB = subjectA.clone(recursive: true)
subjectB.name = "subjectB"
subjectB.position.x = -0.15
content.add(subjectB)
// Manipulation Event Examples
willBegin = content.subscribe(to: ManipulationEvents.WillBegin.self) { event in
print("picked up \(event.entity.name)")
}
willRelease = content.subscribe(to: ManipulationEvents.WillRelease.self) { event in
print("released up \(event.entity.name)")
}
// Collision Event Example
collisionBeganUnfiltered = content.subscribe(to: CollisionEvents.Began.self) { collisionEvent in
print("Collision between \(collisionEvent.entityA.name) and \(collisionEvent.entityB.name)")
}
}
.onDisappear() {
sceneEventExample?.cancel()
sceneEventExample = nil
componentEventExample?.cancel()
componentEventExample = nil
willBegin?.cancel()
willBegin = nil
willRelease?.cancel()
willRelease = nil
collisionBeganUnfiltered?.cancel()
collisionBeganUnfiltered = nil
}
}
}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