View in English

  • Apple Developer
    • Get Started

    Explore Get Started

    • Overview
    • Learn
    • Apple Developer Program

    Stay Updated

    • Latest News
    • Hello Developer
    • Platforms

    Explore Platforms

    • Apple Platforms
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store

    Featured

    • Design
    • Distribution
    • Games
    • Accessories
    • Web
    • Home
    • CarPlay
    • Technologies

    Explore Technologies

    • Overview
    • Xcode
    • Swift
    • SwiftUI

    Featured

    • Accessibility
    • App Intents
    • Apple Intelligence
    • Games
    • Machine Learning & AI
    • Security
    • Xcode Cloud
    • Community

    Explore Community

    • Overview
    • Meet with Apple events
    • Community-driven events
    • Developer Forums
    • Open Source

    Featured

    • WWDC
    • Swift Student Challenge
    • Developer Stories
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Centers
    • Documentation

    Explore Documentation

    • Documentation Library
    • Technology Overviews
    • Sample Code
    • Human Interface Guidelines
    • Videos

    Release Notes

    • Featured Updates
    • iOS
    • iPadOS
    • macOS
    • watchOS
    • visionOS
    • tvOS
    • Xcode
    • Downloads

    Explore Downloads

    • All Downloads
    • Operating Systems
    • Applications
    • Design Resources

    Featured

    • Xcode
    • TestFlight
    • Fonts
    • SF Symbols
    • Icon Composer
    • Support

    Explore Support

    • Overview
    • Help Guides
    • Developer Forums
    • Feedback Assistant
    • Contact Us

    Featured

    • Account Help
    • App Review Guidelines
    • App Store Connect Help
    • Upcoming Requirements
    • Agreements and Guidelines
    • System Status
  • Quick Links

    • Events
    • News
    • Forums
    • Sample Code
    • Videos
 

Vídeos

Abrir menu Fechar menu
  • Coleções
  • Todos os vídeos
  • Sobre

Mais vídeos

  • Sobre
  • Resumo
  • Código
  • Melhor juntos: SwiftUI e RealityKit

    Descubra como integrar perfeitamente o SwiftUI e o RealityKit no visionOS 26. Vamos explorar as melhorias do Model3D, incluindo suporte a animações e compatibilidade com o ConfigurationCatalog, além de demonstrar transições suaves no RealityView. Você aprenderá a usar as animações do SwiftUI para controlar mudanças nos componentes do RealityKit, implementar manipulação interativa, usar os novos componentes do SwiftUI para criar interações mais avançadas e monitorar as alterações do RealityKit com base no seu código do SwiftUI. Também abordaremos o uso da conversão unificada de coordenadas para realizar transformações entre frameworks.

    Capítulos

    • 0:00 - Introdução
    • 1:24 - Aprimoramentos do Model3D
    • 6:13 - Transição para o RealityView
    • 11:52 - Manipulação de objetos
    • 15:35 - Componentes do SwiftUI
    • 19:08 - Fluxo de informações
    • 24:56 - API Unified Coordinate Conversion
    • 27:01 - Animação
    • 29:41 - Próximas etapas

    Recursos

    • Rendering hover effects in Metal immersive apps
    • Canyon Crosser: Building a volumetric hike-planning app
      • Vídeo HD
      • Vídeo SD

    Vídeos relacionados

    WWDC24

    • Compose interactive 3D content in Reality Composer Pro

    WWDC23

    • Discover Observation in SwiftUI

    WWDC21

    • Dive into RealityKit 2

    WWDC20

    • Data Essentials in SwiftUI
  • Buscar neste vídeo...
    • 1:42 - Sparky in Model3D

      struct ContentView: View {
        var body: some View {
          Model3D(named: "sparky")
        }
      }
    • 1:52 - Sparky in Model3D with a name sign

      struct ContentView: View {
        var body: some View {
          HStack {
            NameSign()
            Model3D(named: "sparky")
          }
        }
      }
    • 3:18 - Display a model asset in a Model3D and present playback controls​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

      struct RobotView: View {
        @State private var asset: Model3DAsset?
        var body: some View {
          if asset == nil {
            ProgressView().task { asset = try? await Model3DAsset(named: "sparky") }
          }
        }
      }
    • 3:34 - Display a model asset in a Model3D and present playback controls​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

      struct RobotView: View {
        @State private var asset: Model3DAsset?
        var body: some View {
          if asset == nil {
            ProgressView().task { asset = try? await Model3DAsset(named: "sparky") }
          } else if let asset {
            VStack {
              Model3D(asset: asset)
              AnimationPicker(asset: asset)
            }
          }
        }
      }
    • 4:03 - Display a model asset in a Model3D and present playback controls​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

      struct RobotView: View {
        @State private var asset: Model3DAsset?
        var body: some View {
          if asset == nil {
            ProgressView().task { asset = try? await Model3DAsset(named: "sparky") }
          } else if let asset {
            VStack {
              Model3D(asset: asset)
              AnimationPicker(asset: asset)
              if let animationController = asset.animationPlaybackController {
                RobotAnimationControls(playbackController: animationController)
              }
            }
          }
        }
      }
    • 4:32 - Pause, resume, stop, and change the move the play head in the animation​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

      struct RobotAnimationControls: View {
        @Bindable var controller: AnimationPlaybackController
      
        var body: some View {
          HStack {
            Button(controller.isPlaying ? "Pause" : "Play") {
              if controller.isPlaying { controller.pause() }
              else { controller.resume() }
            }
      
            Slider(
              value: $controller.time,
              in: 0...controller.duration
            ).id(controller)
          }
        }
      }
    • 5:41 - Load a Model3D using a ConfigurationCatalog​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

      struct ConfigCatalogExample: View {
        @State private var configCatalog: Entity.ConfigurationCatalog?
        @State private var configurations = [String: String]()
        @State private var showConfig = false
        var body: some View {
          if let configCatalog {
            Model3D(from: configCatalog, configurations: configurations)
              .popover(isPresented: $showConfig, arrowEdge: .leading) {
                ConfigPicker(
                  name: "outfits",
                  configCatalog: configCatalog,
                  chosenConfig: $configurations["outfits"])
              }
          } else {
            ProgressView()
              .task {
                await loadConfigurationCatalog()
              }
          }
        }
      }
    • 6:51 - Switching from Model3D to RealityView

      struct RobotView: View {
        let url: URL = Bundle.main.url(forResource: "sparky", withExtension: "reality")!
      
        var body: some View {
          HStack {
            NameSign()
            RealityView { content in
              if let sparky = try? await Entity(contentsOf: url) {
                content.add(sparky)
              }
            }
          }
        }
      }
    • 7:25 - Switching from Model3D to RealityView with layout behavior

      struct RobotView: View {
        let url: URL = Bundle.main.url(forResource: "sparky", withExtension: "reality")!
      
        var body: some View {
          HStack {
            NameSign()
            RealityView { content in
              if let sparky = try? await Entity(contentsOf: url) {
                content.add(sparky)
              }
            }
            .realityViewLayoutBehavior(.fixedSize)
          }
        }
      }
    • 8:48 - Switching from Model3D to RealityView with layout behavior and RealityKit animation

      struct RobotView: View {
        let url: URL = Bundle.main.url(forResource: "sparky", withExtension: "reality")!
      
        var body: some View {
          HStack {
            NameSign()
            RealityView { content in
              if let sparky = try? await Entity(contentsOf: url) {
                content.add(sparky)
                sparky.playAnimation(getAnimation())
              }
            }
            .realityViewLayoutBehavior(.fixedSize)
          }
        }
      }
    • 10:34 - Add 2 particle emitters; one to each side of the robot's head

      func setupSparks(robotHead: Entity) {
        let leftSparks = Entity()
        let rightSparks = Entity()
      
        robotHead.addChild(leftSparks)
        robotHead.addChild(rightSparks)
      
        rightSparks.components.set(sparksComponent())
        leftSparks.components.set(sparksComponent())
      
        leftSparks.transform.rotation = simd_quatf(Rotation3D(
          angle: .degrees(180),
          axis: .y))
      
        leftSparks.transform.translation = leftEarOffset()
        rightSparks.transform.translation = rightEarOffset()
      }
      
      // Create and configure the ParticleEmitterComponent
      func sparksComponent() -> ParticleEmitterComponent { ... }
    • 12:30 - Apply the manipulable view modifier

      struct RobotView: View {
        let url: URL
        var body: some View {
          HStack {
            NameSign()
            Model3D(url: url)
              .manipulable()
          }
        }
      }
    • 12:33 - Allow translate, 1- and 2-handed rotation, but not scaling

      struct RobotView: View {
        let url: URL
        var body: some View {
          HStack {
            NameSign()
            Model3D(url: url)
              .manipulable(
                operations: [.translation,
                             .primaryRotation,
                             .secondaryRotation]
             )
          }
        }
      }
    • 12:41 - The model feels heavy with high inertia

      struct RobotView: View {
        let url: URL
        var body: some View {
          HStack {
            NameSign()
            Model3D(url: url)
              .manipulable(inertia: .high)
          }
        }
      }
    • 13:18 - Add a ManipulationComponent to an entity​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

      RealityView { content in
        let sparky = await loadSparky()
        content.add(sparky)
        ManipulationComponent.configureEntity(sparky)
      }
    • 13:52 - Add a ManipulationComponent to an entity​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​ with configuration

      RealityView { content in
        let sparky = await loadSparky()
        content.add(sparky)
        ManipulationComponent.configureEntity(
          sparky,
          hoverEffect: .spotlight(.init(color: .purple)),
          allowedInputTypes: .all,
          collisionShapes: myCollisionShapes()
        )
      }
    • 14:08 - Manipulation interaction events

      public enum ManipulationEvents {
      
        /// When an interaction is about to begin on a ManipulationComponent's entity
        public struct WillBegin: Event { }
        
        /// When an entity's transform was updated during a ManipulationComponent
        public struct DidUpdateTransform: Event { }
      
        /// When an entity was released
        public struct WillRelease: Event { }
      
        /// When the object has reached its destination and will no longer be updated
        public struct WillEnd: Event { }
      
        /// When the object is directly handed off from one hand to another
        public struct DidHandOff: Event { }
      }
    • 14:32 - Replace the standard sounds with custom ones

      RealityView { content in
        let sparky = await loadSparky()
        content.add(sparky)
      
        var manipulation = ManipulationComponent()
        manipulation.audioConfiguration = .none
        sparky.components.set(manipulation)
      
        didHandOff = content.subscribe(to: ManipulationEvents.DidHandOff.self) { event in
          sparky.playAudio(handoffSound)
        }
      }
    • 16:19 - Builder based attachments

      struct RealityViewAttachments: View {
        var body: some View {
          RealityView { content, attachments in
            let bolts = await loadAndSetupBolts()
            if let nameSign = attachments.entity(
              for: "name-sign"
            ) {
              content.add(nameSign)
              place(nameSign, above: bolts)
            }
            content.add(bolts)
          } attachments: {
            Attachment(id: "name-sign") {
              NameSign("Bolts")
            }
          }
          .realityViewLayoutBehavior(.centered)
        }
      }
    • 16:37 - Attachments created with ViewAttachmentComponent

      struct AttachmentComponentAttachments: View {
        var body: some View {
          RealityView { content in
            let bolts = await loadAndSetupBolts()
            let attachment = ViewAttachmentComponent(
                rootView: NameSign("Bolts"))
            let nameSign = Entity(components: attachment)
            place(nameSign, above: bolts)
            content.add(bolts)
            content.add(nameSign)
          }
          .realityViewLayoutBehavior(.centered)
        }
      }
    • 17:04 - Targeted to entity gesture API

      struct AttachmentComponentAttachments: View {
        @State private var bolts = Entity()
        @State private var nameSign = Entity()
      
        var body: some View {
          RealityView { ... }
          .realityViewLayoutBehavior(.centered)
          .gesture(
            TapGesture()
              .targetedToEntity(bolts)
              .onEnded { value in
                nameSign.isEnabled.toggle()
              }
          )
        }
      }
    • 17:10 - Gestures with GestureComponent

      struct AttachmentComponentAttachments: View {
        var body: some View {
          RealityView { content in
            let bolts = await loadAndSetupBolts()
            let attachment = ViewAttachmentComponent(
                rootView: NameSign("Bolts"))
            let nameSign = Entity(components: attachment)
            place(nameSign, above: bolts)
            bolts.components.set(GestureComponent(
              TapGesture().onEnded {
                nameSign.isEnabled.toggle()
              }
            ))
            content.add(bolts)
            content.add(nameSign)
          }
          .realityViewLayoutBehavior(.centered)
        }
      }
    • 0:00 - Introdução
    • Saiba mais sobre os aprimoramentos do SwiftUI do RealityKit que permitem a integração perfeita da interface do usuário tradicional e do conteúdo 3D interativo. As principais atualizações incluem aprimoramentos no Model3D e no RealityView, a introdução da API Object Manipulation, novos tipos de componente, fluxo de dados bidirecional entre o SwiftUI e o RealityKit, conversão de espaço de coordenadas facilitada e animações orientadas por SwiftUI para componentes do RealityKit.

    • 1:24 - Aprimoramentos do Model3D
    • No visionOS 26, o Model3D permite exibir modelos 3D com animações e carregar a partir de um "ConfigurationCatalog". Agora você pode criar experiências 3D interativas com apenas algumas linhas de código. Use o novo tipo "Model3DAsset" para carregar e controlar animações, e o "ConfigurationCatalog" permite alternar entre diferentes representações de uma entidade, como roupas ou tipos de corpo. Para demonstrar esses recursos, temos o exemplo de um robô chamado Sparky, que você pode animar, vestir com diferentes roupas e controlar usando visualizações e seletores SwiftUI, preparando-o para interagir com outros robôs em uma estufa virtual.

    • 6:13 - Transição para o RealityView
    • Para adicionar um emissor de partículas a um modelo 3D em tempo de execução, você deve alternar do uso de "Model3D" para "RealityView" no RealityKit porque o Model3D não suporta a adição de componentes. O RealityView é carregado com a entidade modelo, mas isso causa problemas no layout, pois o padrão ocupa todo o espaço disponível. O modificador "realityViewLayoutBehavior" é aplicado com "fixedSize" para resolver esse problema, ajustando o RealityView ao modelo. Há três opções de comportamento diferentes de "realityViewLayoutBehavior". "flexible", "centered" e "fixedSize", cada um afetando o ponto de origem do RealityView sem reposicionar as entidades. Use o Reality Composer Pro para projetar emissores de partículas que podem ser configurados no código. Emissores de partículas são adicionados a entidades como componentes. O RealityKit tem como base o paradigma "Entity Component System". O exemplo inclui emissores de partículas para criar efeitos de faísca, envolvendo entidades invisíveis como contêineres para as faíscas. O RealityView é ótimo para criação detalhada e controle refinado sobre o comportamento do conteúdo 3D, enquanto o Model3D é adequado para exibir assets 3D independentes. Você pode fazer a transição suave entre os dois conforme necessário.

    • 11:52 - Manipulação de objetos
    • A nova API Object Manipulation no visionOS 26 permite interagir com objetos virtuais em apps que usam SwiftUI e RealityKit. As pessoas podem mover, girar e escalar objetos com as mãos, e até mesmo passar objetos entre as mãos. Para visualizações do SwiftUI, você pode aplicar o modificador 'manipulable', permitindo a personalização das operações suportadas e a inércia do objeto. No RealityKit, adicione o "ManipulationComponent" às entidades por meio da função estática "configureEntity", que também adiciona componentes de colisão, destino de entrada e efeito de foco. A função tem vários parâmetros para personalização de comportamento. Assine "ManipulationEvents" acionados durante interações, como inícios, paradas, atualizações, lançamentos e transferências, para atualizar o estado do app e personalizar a experiência, incluindo a substituição de sons padrão por recursos de áudio personalizados.

    • 15:35 - Componentes do SwiftUI
    • Os novos componentes do SwiftUI RealityKit melhoram a interação e a conexão do usuário dentro das cenas do RealityKit. Esses componentes permitem integrar perfeitamente visualizações do SwiftUI em ambientes 3D. Os principais recursos incluem o "ViewAttachmentComponent", que permite adicionar visualizações do SwiftUI diretamente a entidades; o "GestureComponent", tornando as entidades responsivas ao toque e movimentos; e o "PresentationComponent", que permite apresentar visualizações do SwiftUI, como popovers, dentro da cena. O parâmetro de configuração no "PresentationComponent" define o tipo de apresentação para exibição. Essas melhorias simplificam o processo de desenvolvimento, permitindo criar experiências mais dinâmicas e envolventes. No exemplo, um robô chamado Bolts pode ter um sinal de nome que liga e desliga com um movimento de toque, e as pessoas podem escolher a roupa dele em um menu popover, tudo dentro do ambiente imersivo do RealityKit.

    • 19:08 - Fluxo de informações
    • No visionOS 26, as entidades agora são observáveis, o que permite que entidades, como o robô Bolts, notifiquem outro código quando suas propriedades mudarem. Isso é particularmente útil para rastrear os movimentos do Bolts enquanto rega as plantas na estufa. O exemplo usa o SwiftUI para implementar um minimapa que exibe a posição do Bolts em tempo real. Acessando a propriedade de posição observável do Bolts, o SwiftUI atualiza automaticamente o minimapa sempre que Bolts se move. Esse fluxo de dados bidirecional entre o SwiftUI e o RealityKit, habilitado por entidades observáveis, é uma nova ferramenta significativa. Essa nova funcionalidade observável também introduz o potencial de loops infinitos, caso não seja gerenciada com cuidado. Para evitar esses loops, atente-se a onde você modifica o estado observado. Não faça alterações no estado observado dentro do fechamento "update" do "RealityView", porque isso pode desencadear um ciclo de atualização recursivo. Em vez disso, faça modificações em locais específicos, como sistemas personalizados, fechamentos por movimento ou o fechamento "make", que estão fora do escopo da avaliação do corpo de visualização da SwiftUI. Dividindo visualizações maiores em visualizações menores e independentes e tendo cautela quanto a onde o estado é modificado, você pode garantir um fluxo de dados suave e eficiente entre o SwiftUI e o RealityKit, evitando loops infinitos e melhorando o desempenho geral do app.

    • 24:56 - API Unified Coordinate Conversion
    • A nova API de conversão de coordenadas unificadas preenche a lacuna entre o RealityKit e o SwiftUI. Implementando o protocolo "CoordinateSpace3D", você pode converter valores perfeitamente entre os dois frameworks. Isso permite calcular a distância absoluta entre Bolts, uma entidade no RealityKit, e Sparky, um Model3D em SwiftUI, à medida que se aproximam, gerando faíscas dinamicamente com base em sua proximidade.

    • 27:01 - Animação
    • No visionOS 26, é possível aproveitar as APIs de animação do SwiftUI para animar implicitamente as mudanças de componentes do RealityKit. Isso permite movimentos suaves e dinâmicos de entidades simplesmente definindo componentes compatíveis dentro de um bloco de animação. Existem dois métodos para conseguir isso: usando "content.animate()" dentro de um RealityView ou chamando "Entity.animate()" diretamente. Essa integração permite comportamentos personalizados de liberação ao manipular entidades, tornando as interações com objetos 3D mais envolventes e divertidas. Vários componentes do RealityKit, incluindo Transformar, Áudio, Modelo e Luz, oferecem suporte a essas animações implícitas.

    • 29:41 - Próximas etapas
    • Use essa nova conexão entre SwiftUI e RealityKit para criar apps espaciais inovadores, integrando componentes SwiftUI com cenas do RealityKit, permitindo interações dinâmicas entre os mundos virtual e físico e inspirando novas possibilidades no desenvolvimento de apps.

Developer Footer

  • Vídeos
  • WWDC25
  • Melhor juntos: SwiftUI e RealityKit
  • Open Menu Close Menu
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • Icon Composer
    • SF Symbols
    Open Menu Close Menu
    • Accessibility
    • Accessories
    • Apple Intelligence
    • Audio & Video
    • Augmented Reality
    • Business
    • Design
    • Distribution
    • Education
    • Games
    • Health & Fitness
    • In-App Purchase
    • Localization
    • Maps & Location
    • Machine Learning & AI
    • Security
    • Safari & Web
    Open Menu Close Menu
    • Documentation
    • Downloads
    • Sample Code
    • Videos
    Open Menu Close Menu
    • Help Guides & Articles
    • Contact Us
    • Forums
    • Feedback & Bug Reporting
    • System Status
    Open Menu Close Menu
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles
    • Feedback Assistant
    Open Menu Close Menu
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program
    • Mini Apps Partner Program
    • News Partner Program
    • Video Partner Program
    • Security Bounty Program
    • Security Research Device Program
    Open Menu Close Menu
    • Meet with Apple
    • Apple Developer Centers
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Academies
    • WWDC
    Read the latest news.
    Get the Apple Developer app.
    Copyright © 2026 Apple Inc. All rights reserved.
    Terms of Use Privacy Policy Agreements and Guidelines