Getting started with RealityKit: Component Entity System

Part 1: The new SCNNode

Max Cobb
5 min readJul 28, 2019

--

This article is part of a series, the main article which points to all in the series is this one:

Having used SceneKit in the past, I noticed right away that there are some pieces missing from RealityKit. However, rather than focusing on that I’m going to focus on showing how to use protocol oriented programming (pop) within RealityKit, which it is heavily suggesting you use (with good reason).

The pop approach is used to prevent deep class hierarchies, avoids tight coupling and pushes you away from even thinking about multiple inheritance; which isn’t supported in Swift anyway.

ARView Scene Structure, source: developer.apple.com

With RealityKit everything inside your scene is an Entity, this is the only class you now inherit from, and from here you can build everything into your ARView with the use of adding Components. If you’ve used SceneKit in the past, Entity is in many ways the new alternative to SCNNode. These components can turn your Entity to anything from an Anchor, to a Model or even a spotlight. For a list of all the possible components, and how to register your own components, take a look here.

It is important to note that you can not add an Entity to the scene unless it conforms to the HasAnchoring protocol, or is added as a child to an Entity with this property, such as an AnchorEntity. I’ll cover the Anchoring property in a later article.

To create your own Entity subclass, you’ll need to inherit from Entity, add any relevant components, and protocols, such as HasModel, HasAnchoring or HasCollision. Here’s an example of a class with just one of those components and protocols:

class CustomBox: Entity, HasModel {
required init(color: UIColor) {
super.init()
self.components[ModelComponent] = ModelComponent(
mesh: .generateBox(size: [1, 0.2, 1]),
materials: [SimpleMaterial(
color: color,
isMetallic: false)
]
)
}
}

The HasModel protocol also gives your entity a property model, so the same as above can be achieved by setting self.model = ModelComponent(...).

Showing the cuboid in the ARView (here it is a child of an AnchorEntity)

As you can see here I’ve created a subclass of Entity, and given it the HasModel protocol, so we know that this Entity should display a model. The model geometry and material have been added by adding the property to the Entity’s ComponentSet. Adding any component to an Entity is done in a very similar way.

If, for example, you wanted the above Entity to have a model and also be tappable, you’d need to add the HasCollision protocol alongside the HasModel protocol, and then also add to the CollisionComponent. The result would look as such:

class CustomBox: Entity, HasModel, HasCollision {
required init(color: UIColor) {
super.init()
self.model = ModelComponent(
mesh: .generateBox(size: [1, 0.2, 1]),
materials: [SimpleMaterial(
color: color,
isMetallic: false)
]
)
self.generateCollisionShapes(recursive: true)
}
}

You could also set the CollisionComponent explicitly, such as this:

self.components[CollisionComponent] = CollisionComponent(
shapes: [.generateBox(size: [1, 0.2, 1])]
)
// or the shorthandself.collision = CollisionComponent(
shapes: [.generateBox(size: [1, 0.2, 1])]
)

You might set the CollisionComponent explicitly if you wanted the collision area to be slightly larger than your model and its sub entities, for example.

There’s lots more you can do with CollisionComponent such as detecting collisions, as shown in my other article:

Creating Custom Components

The built-in Entity types I mentioned earlier might often be all you need to get started. Here’s a few standard Entity types along with their given components:

Entity, AnchorEntity and ModelEntity Structures, source: developer.apple.com

However, if you want to add properties, you could do that by just adding a property inside the class:

class CustomBox: Entity {
var isRevealed = false
var id: Int
}

Alternatively you could create your own component to have all the relevant variables together, which also makes it easy to use this new component across class types. Here’s an example:

struct CardComponent: Component, Codable {
var isRevealed = false
var id: Int
}

If you want to use your own Component type like above, be sure to register it. This must be done once for each custom component type; it needn’t be called for the build-in component types such as ModelComponent or AnchoringComponent. For the above component put this somewhere in your code before initializing your first Entity using your new custom component.

CardComponent.registerComponent()

Any component must be a struct which conforms to both the Component and Codable protocols, beyond that the properties are up to you; you can put methods in there and conform to more protocols if you wish.

If we wanted to follow what has been done with the rest of RealityKit so far, I’d recommend creating protocol to have all the properties and methods related to the cards together, and bring it into your class like this:

protocol HasCard {}extension HasCard where Self: Entity {
var card: CardComponent {
get { components[CardComponent] ?? CardComponent(id: -1) }
set { components[CardComponent] = newValue }
}
var cardID: Int {
self.card.id
}
var isRevealed: Bool {
return self.card.isRevealed
}
}
extension CustomBox: HasCard {}

This way you can quickly look up your card details by accessing those methods given to you, while keeping all the properties relevant to the fact that your entity is a card all together. You can even put methods inside your HasCard protocol which can animate your Entity, which is what I’ve done in this class here.

For more examples, and to see these things in action, I’ve created a repository where I’m adding parts of RealityKit as I reach them into a game, click the link below to see it. Also if you have any suggestions of better methods of implementing Apple’s new framework, I encourage you to open a Pull Request on the below repository.

If you’ve enjoyed this article and want to see more in this RealityKit series; tap the 👏 button (you can do this 50 times 😱). If you have specific requests of RealityKit features to cover leave a comment below.

--

--

Max Cobb

Excited about all things Augmented Reality! Developer Evangelist at Agora.io.