Getting started with RealityKit: Collisions and other Events

Part 4: subscribing to RealityKit Events

Max Fraser Cobb
Aug 12, 2019 · 5 min read

There are several times when you might want to create a callback within an Augmented Reality scene, such as when an AnchorEntity has found an appropriate anchor in the scene or when two Entities models overlap. These events can be listened to via the subscribe(to:on:_:) method.

There are a few different type of standard events you can listen to in RealityKit, those include: CollisionEvents, for when a collision begins, updates and ends; AnimationEvents, for doing something when an animation completes, loops, or is terminated; or even a SceneEvent, such as AnchoredStateChanged, when an AnchorEntity has been anchored in the scene, or Update, which is called every frame.

These events are all executed in similar ways; so we’re just going to dive in and see how you might use CollisionEvents, then hopefully the learnings from that can easily be applied to any of the other Events.


CollisionEvents

To get started with CollisionEvents in RealityKit you’ll need to have two objects that both have a CollisionComponent component. If you haven’t read my earlier article on adding components to Entities, I’d recommend that before continuing:

I’ve created a sample class called CustomBox, which is a subclass of Entity and conforms to HasModel, HasCollision and HasAnchoring, for details on how that class’s structure looks, check out this gist:

To create a callback for a CollisionEvent you need to tell the Scene to subscribe to the event. If you’re checking for the collision between two entities, I’d recommend just adding the subscription to one of those entities, otherwise you’ll get two callbacks. Here’s an example of a subscription you could add to the scene to call whenever there is a collision of any kind.

let beginSub = self.scene.subscribe(
to: CollisionEvents.Began.self
) { event in
print("collision started")
}

I’m saving the response to subscribe for a very specific reason to do with memory management which I’ll mention below. No subscriptions will work without a persistant reference.

You can then get which two entities have collided by taking entityA and entityB from the event variable, and then seeing which entities in your scene they are. If instead you wanted to have a more specific event to check for, say for example if your entity myBox collides with anything, you could add that to the subscribe call as another parameter as such.

let myBox = CustomBox()
let beginSub = self.scene.subscribe(
to: CollisionEvents.Began.self,
on: myBox
) { event in
print("collision started")
}

What I want to do here is simply change the model’s material to a red colour when the collision occurs, and then back to normal when it ends.

let box1 = CustomBox(
color: .green,
position: [0.6,-1,-2]
)
self.scene.anchors.append(box1)
let box2 = CustomBox(
color: .green,
position: [-0.6,-1, -2]
)
self.scene.anchors.append(box2)
let beginSub = self.scene.subscribe(
to: CollisionEvents.Began.self
on: box1
) { event in
// Get both of the entities from the event
let boxA = event.entityA as? CustomBox
let boxB = event.entityB as? CustomBox
// Change the materials
boxA?.model?.materials = [
SimpleMaterial(color: .red, isMetallic: false)
]
boxB?.model?.materials = [
SimpleMaterial(color: .red, isMetallic: false)
]
}
let endSub = self.scene.subscribe(
to: CollisionEvents.Ended.self,
on: box1
) { event in
// Get both of the entities from the event
let boxA = event.entityA as? CustomBox
let boxB = event.entityB as? CustomBox
// Change the materials
boxA?.model?.materials = [
SimpleMaterial(color: .green, isMetallic: false)
]
boxB?.model?.materials = [
SimpleMaterial(color: .green, isMetallic: false)
]
}

The positions set in the above code means that the cuboids will be placed in front of the user at the initializing of the scene, and not touching with one on the left, the other on the right.

I have also added EntityGestures to one cube so we can move it around, for more information on that I suggest you check out my pervious post on gestures in RealityKit:

One final thing which needs to be added to ensure that these functions will be called is that you need to always be able to reference the subscribed events. I achieved this by adding a parameter to my CustomBox class of type [Cancellable], and when adding a new subscription I would append it to that array. To see how this is done, see this Gist:

Referencing the subscription is extremely important to avoid your scene observing too many events. Doing it this way ensures that all you need to do to get rid of an event listener is either delete the Entity or clear the Entity’s array, which in this case is called collisionSubs.

Along with the above Gists, the only things you’ll need to call are:

// Add box1 and box2 to the scene
let box1 = CustomBox(
color: .green,
position: [0.6,-1,-2]
)
self.scene.anchors.append(box1)
let box2 = CustomBox(
color: .green,
position: [-0.6,-1, -2]
)
self.scene.anchors.append(box2)
// Add translation EntityGesture to box1
installGestures(.translation, for: box1)
// Call the bespoke addCollisions function (click to see)
box1.addCollisions()

And you will have two boxes which an collide with each other as in the above GIF.


The principles from the above examples can be applied to many scenarios, but hopefully this article has explained the simple how-to’s of both detecting CollisionEvents and in turn also the general use and implementation of Events in RealityKit.

If you want to see some more examples using subscribe(to:on:_:) I have implemented some subscriptions in my public RealityKit repo, which can be found here:


Thanks for reading, I hope you’ve enjoyed this post. Be sure to check out my other RealityKit posts to read more about how to use Apple’s latest Augmented Reality framework.

And of course, don’t forget to clap! 👏👏👏

Max Fraser Cobb

Written by

Augmented Reality Engineer and mathematician. Excited for the future of AR and what amazing people are going to create.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade