Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2023 EssentialsSpatial Computing

WWDC23 · 28 min · Essentials / Spatial Computing

Build spatial experiences with RealityKit

Discover how RealityKit can bring your apps into a new dimension. Get started with RealityKit entities, components, and systems, and learn how you can add 3D models and effects to your app on visionOS. We’ll also take you through the RealityView API and demonstrate how to add 3D objects to windows, volumes, and spaces to make your apps more immersive. And we’ll explore combining RealityKit with spatial input, animation, and spatial audio.

Watch at developer.apple.com ↗

Transcript all transcripts

Chapters

Code shown on screen · 13 snippets

Model3D swift · at 3:40 ↗
import SwiftUI
import RealityKit

struct GlobeModule: View {
    var body: some View {
        Model3D(named: "Globe") { model in
            model
                .resizable()
                .scaledToFit()
        } placeholder: {
          	ProgressView()
        }
    }
}
Volumetric window swift · at 5:52 ↗
import SwiftUI
import RealityKit

// Define a volumetric window.
struct WorldApp: App {
    var body: some SwiftUI.Scene {
        // ...

        WindowGroup(id: "planet-earth") {
            Model3D(named: "Globe")
        }
        .windowStyle(.volumetric)
        .defaultSize(width: 0.8, height: 0.8, depth: 0.8, in: .meters)
    }
}
ImmersiveSpace swift · at 7:31 ↗
import SwiftUI
import RealityKit

// Define a immersive space.
struct WorldApp: App {
    var body: some SwiftUI.Scene {
        // ...

        ImmersiveSpace(id: "objects-in-orbit") {
            RealityView { content in
                // ...
            }
        }
    }
}
RealityView swift · at 12:40 ↗
import SwiftUI
import RealityKit

struct Orbit: View {
    let earth: Entity

    var body: some View {
        RealityView { content in
            content.add(earth)
        }
    }
}
RealityView asynchronous loading and entity positioning swift · at 12:54 ↗
import SwiftUI
import RealityKit

struct Orbit: View {
    var body: some View {
        RealityView { content in
            async let earth = ModelEntity(named: "Earth")
            async let moon = ModelEntity(named: "Moon")

            if let earth = try? await earth, let moon = try? await moon {
                content.add(earth)
                content.add(moon)
                moon.position = [0.5, 0, 0]
            }
        }
    }
}
Earth rotation swift · at 13:54 ↗
import SwiftUI
import RealityKit

struct RotatedModel: View {
    var entity: Entity
    var rotation: Rotation3D

    var body: some View {
        RealityView { content in
            content.add(entity)
        } update: { content in
            entity.orientation = .init(rotation)
        }
   }
}
Converting co-ordinate spaces swift · at 14:27 ↗
import SwiftUI
import RealityKit

struct ResizableModel: View {
    var body: some View {
        GeometryReader3D { geometry in
            RealityView { content in
                if let earth = try? await ModelEntity(named: "Earth") {
                    let bounds = content.convert(geometry.frame(in: .local),
                                                 from: .local, to: content)
                    let minExtent = bounds.extents.min()
                    earth.scale = [minExtent, minExtent, minExtent]
                }
            }
        }
    }
}
Play an animation swift · at 14:56 ↗
import SwiftUI
import RealityKit

struct AnimatedModel: View {
    @State var subscription: EventSubscription? 

    var body: some View {
        RealityView { content in
            if let moon = try? await Entity(named: "Moon"),
               let animation = moon.availableAnimations.first {
                moon.playAnimation(animation)
                content.add(moon)
            }
            subscription = content.subscribe(to: AnimationEvents.PlaybackCompleted.self) {
                // ...
            }
       }
   }
}
Adding a drag gesture swift · at 18:31 ↗
import SwiftUI
import RealityKit

struct DraggableModel: View {
    var earth: Entity

    var body: some View {
        RealityView { content in
            content.add(earth)
        }
        .gesture(DragGesture()
            .targetedToEntity(earth)
            .onChanged { value in
                earth.position = value.convert(value.location3D,
                                               from: .local, to: earth.parent!)
            })
    }
}
Playing a transform animation swift · at 20:20 ↗
// Playing a transform animation
let orbit = OrbitAnimation(name: "Orbit",
                           duration: 30,
                           axis: [0, 1, 0],
                           startTransform: moon.transform,
                           bindTarget: .transform,
                           repeatMode: .repeat)

if let animation = try? AnimationResource.generate(with: orbit) {
    moon.playAnimation(animation)
}
Adding audio swift · at 22:12 ↗
// Create an empty entity to act as an audio source.
let audioSource = Entity()

// Configure the audio source to project sound out in a tight beam.
audioSource.spatialAudio = SpatialAudioComponent(directivity: .beam(focus: 0.75))

// Change the orientation of the audio source (rotate 180º around the Y axis).
audioSource.orientation = .init(angle: .pi, axis: [0, 1, 0])

// Add the audio source to a parent entity, and play a looping sound on it.
if let audio = try? await AudioFileResource(named: "SatelliteLoop",
                                            configuration: .init(shouldLoop: true)) {
    satellite.addChild(audioSource)
    audioSource.playAudio(audio)
}
Defining a custom component swift · at 23:47 ↗
import RealityKit

// Components are data attached to an Entity.
struct TraceComponent: Component {
    var mesh = TraceMesh()
}

// Entities contain components, identified by the component’s type.
func updateTrace(for entity: Entity) {
    var component = entity.components[TraceComponent.self] ?? TraceComponent()
    component.update()
    entity.components[TraceComponent.self] = component
}

// Codable components can be added to entities in Reality Composer Pro.
struct PointOfInterestComponent: Component, Codable {
    var name = ""
}
Defining a system swift · at 24:51 ↗
import SwiftUI
import RealityKit

// Systems supply logic and behavior.
struct TraceSystem: System {
    static let query = EntityQuery(where: .has(TraceComponent.self))
    
    init(scene: Scene) {
        // ...
    }

    func update(context: SceneUpdateContext) {
         // Systems often act on all entities matching certain conditions.
        for entity in context.entities(Self.query, updatingSystemWhen: .rendering) {
            addCurrentPositionToTrace(entity)
        }
    }
}

// Systems run on all RealityKit content in your app once registered.
struct MyApp: App {
    init() {
        TraceSystem.registerSystem()
    }
}

Resources