How would I render something like 10,000 cubes efficiently in RealityKit, with the ability to animate each entities parameters like translation, scale, rotation independently?
If I try to add many entities to a scene, which all share the same ModelComponent, that ends up with one draw call per entity, which quickly slows down. In SceneKit if I add many SCNNode and share the same SCNGeometry then SceneKit will use instancing under the hood and only perform one draw call for many objects, but I can't seem to get RealityKit to do the same.
For example, something like this that draws a 10x10 grid of cube on the screen ends up with 100 draw call, even though the ModelComponent (mesh + materials) are all shared.
let material = UnlitMaterial(color: .red)
let modelComponent = ModelComponent(
mesh: .generateBox(size: 0.1),
materials: [material]
)
let containerEntity = Entity()
for i in 0..<100 {
let modelEntity = ModelEntity()
modelEntity.model = modelComponent
modelEntity.transform.translation = [
-0.75 + Float(i % 10) * 0.15,
-0.25 + floor(Float(i) / 10.0) * 0.15,
0
]
containerEntity.addChild(modelEntity)
}
let anchor = AnchorEntity()
anchor.addChild(containerEntity)
scene.addAnchor(anchor)
I know I could generate a custom MeshResource that has all the cube vertices defined in it and uses instancing instead, but then that makes things harder overall instead of just using the default Entity API provided by RealityKit.
I want to be able to animate the cubes and potentially apply some Physics to the models as well, so making a custom Mesh just makes that harder.
Thanks.
At WWDC25, the MeshInstancesComponent was introduced. It performs GPU instancing on the ModelComponent on the same Entity. Yet, for some reason, this component doesn't work with RealityKit procedural geometry and doesn't allow generating more than 1000 instances from target geometry, but I'm sure that both restrictions will be lifted in the near future.
Test my code:
import SwiftUI
import RealityKit
struct ContentView : View {
let count = 1000
var body: some View {
RealityView { rvc in
let entity = try? await Entity(named: "ball")
let model = entity?.findEntity(named: "ball_soccerball_relistic_lod0") as! ModelEntity
var component = MeshInstancesComponent()
let instances = try? LowLevelInstanceData(instanceCount: count)
component[partIndex: 0] = instances
instances?.withMutableTransforms {
for i in 0 ..< count {
let scale = Float.random(in: 0.5...1.5)
let angle = Float.random(in: 0.0...1.0)
let xPos = Float.random(in: -10.0...10.0)
let zPos = Float.random(in: -10.0...10.0)
let transform = Transform(scale: .init(repeating: scale),
rotation: .init(angle: .pi / 2,
axis: [0, angle, 0]),
translation: [xPos, 0, zPos])
$0[i] = transform.matrix
}
}
model.components.set(component)
rvc.add(model)
}
}
}

Unfortunately, in previous versions of iOS, macOS and visionOS there's no instanced rendering in RealityKit. So, this is the area where a deprecated SceneKit definitely wins. RealityKit 4.0 API has MeshResource.Instance object but it's misinterpreted (it's rather a mere sample than a lightweight copy of geometry). So if you have 10K cubes then you'll get 10K draw calls each frame. And nothing else. In this case, rendering becomes a headache, because despite the fact that devices are becoming more and more powerful, iOS still has a limit on the number of polygons in the scene - there should be no more than 100K polygons per scene (visionOS limit is 500K polygons). This means that if you have 10K cubes, each of which has at least 12 triangle polygons, you are exceeding the iOS recommended scene's limit by 20K polygons.
Now regarding the animation of your cubes. This is where RealityKit's Entity-Component-System (ECS) paradigm comes into play. Systems can simultaneously work with several components and, using their update(context:) methods, can apply a logic to many entities that meet certain criteria. This allows developer to do any per-frame calculations for all grouped-by-criteria entities (not for every separate entity) only once per frame. You can deploy as many systems in RealityKit's scene as you want. ECS is a magic wand in many cases.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With