RealityKit visionOS Developer
Overview
Use this skill to implement RealityKit-based spatial experiences on visionOS, focusing on entity composition, component-driven behavior, and ECS systems that update every frame.
Quick start workflow
- Start with
RealityViewand itsRealityViewContentto add entities and attach components. - Load assets asynchronously and build a clean entity hierarchy.
- Add the components you need for rendering, interaction, physics, audio, and animation.
- Prefer
ViewAttachmentComponentwhen embedding SwiftUI into 3D; avoid theRealityViewattachments closure. - Register custom components and systems (
Component.registerComponent(),System.registerSystem()) so they decode and update correctly. - Use custom systems for continuous behavior and profile performance on device.
Core concepts
Entities and components
- Entities are lightweight containers; behavior comes from components.
- Prefer composition over inheritance and use custom
Component+Codablewhen you need per-entity state. - Register custom components once with
Component.registerComponent()before use. - Keep entity transforms and component updates on the main actor.
RealityView and attachments
- Use
RealityViewto bridge SwiftUI and RealityKit. - Load assets with
Entity(named:)orEntity(contentsOf:)asynchronously and handle errors. - Prefer
ViewAttachmentComponentfor SwiftUI overlays in 3D and avoid theRealityViewattachments closure.
Systems and queries
- Use a custom
Systemfor continuous, per-frame behavior. - Query entities with
EntityQuery+QueryPredicateand process them inupdate(context:). - Use
SystemDependencyto control update order when multiple systems interact.
Interaction and physics
- Add
CollisionComponentandInputTargetComponentfor input-driven entities. - Use
ManipulationComponentfor built-in spatial interactions andGestureComponentfor custom gestures. - Keep physics bodies and collision shapes aligned with your mesh scale.
Rendering, lighting, and audio
- Use
ImageBasedLightComponentandGroundingShadowComponentto anchor content visually. - Use
EnvironmentBlendingComponentfor spatially aware compositing. - Use
SpatialAudioComponentandReverbComponentfor immersive soundscapes.
Implementation patterns
RealityView async load
RealityView { content in
do {
let entity = try await Entity(named: "Scene")
content.add(entity)
} catch {
print("Failed to load entity: \(error)")
}
}
Interactive entity setup
let entity = ModelEntity(mesh: .generateBox(size: 0.1))
entity.components.set(CollisionComponent(shapes: [.generateBox(size: [0.1, 0.1, 0.1])]))
entity.components.set(InputTargetComponent())
entity.components.set(ManipulationComponent())
Custom system skeleton
import RealityKit
struct SpinComponent: Component, Codable {
var speed: Float
}
struct SpinSystem: System {
static let query = EntityQuery(where: .has(SpinComponent.self))
init(scene: Scene) {}
func update(context: SceneUpdateContext) {
for entity in context.entities(matching: Self.query, updatingSystemWhen: .rendering) {
guard let spin = entity.components[SpinComponent.self] else { continue }
entity.transform.rotation *= simd_quatf(angle: spin.speed * Float(context.deltaTime), axis: [0, 1, 0])
}
}
}
SpinSystem.registerSystem()
Pitfalls and checks
- Always load assets asynchronously; avoid blocking the main actor.
- Avoid
ARViewon visionOS; useRealityView. - Add
CollisionComponent+InputTargetComponentfor draggable or tappable entities. - Use a custom
Systemfor continuous behavior instead of theRealityViewupdate closure. - Mesh generation is limited to
box,sphere,plane,cylinder, andcone.
References
- references/components.md - RealityKit component catalog for visionOS.
- references/systems.md - RealityKit systems API surface and ECS utilities.