스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
RealityKit으로 공간 경험 빌드하기
RealityKit을 써서 앱을 새로운 차원으로 끌어올리는 방법을 알아보세요. RealityKit 엔티티, 컴포넌트, 시스템을 시작하고 visionOS 앱에 3D 모델 및 효과를 추가하는 방법을 설명합니다. 또한 RealityView API를 살펴보고 윈도우, 볼륨, 공간에 3D 객체를 추가하여 앱의 몰입감을 높이는 방법을 보여드립니다. 그리고 RealityKit과 공간 입력, 애니메이션, 공간 음향을 결합하는 방법을 확인해 보세요.
챕터
- 0:00 - Introduction
- 2:50 - RealityKit and SwiftUI
- 9:36 - Entities and components
- 12:20 - RealityView
- 15:37 - Input, animation and audio
- 23:00 - Custom systems
- 26:15 - Wrap-up
리소스
관련 비디오
WWDC23
-
다운로드
♪ 감미로운 인스트루멘탈 힙합 ♪ ♪ 안녕하세요, 저는 존이고 RealityKit 팀의 엔지니어입니다 오늘 공간 경험을 만들 수 있는 새로운 RealityKit를 소개하게 되어 기쁩니다 RealityKit는 3D 모델 및 효과를 사실적으로 렌더링하고 애니메이션으로 만들며 시뮬레이션하는 프레임워크입니다 저희는 2019년에 RealityKit를 도입했고 그 이후로 새로운 기능을 많이 추가했습니다 다른 기기에서 앱을 빌드할 때 RealityKit를 이미 사용해 보셨다면 공통점이 많다는 사실을 알게 되실 겁니다 RealityKit를 사용하면 앱의 2D 윈도우를 3D 콘텐츠로 증강하고 별도 윈도우의 전면 중앙에 3D 콘텐츠를 배치하거나 자신과 주변 환경을 몰입형 경험으로 구현할 수 있습니다 RealityKit는 Apple 플랫폼의 핵심 3D 프레임워크이며 특히 xrOS에서는 많은 기능을 제공합니다 이 프레젠테이션에서는 엔티티와 컴포넌트, RealityView와 같은 주요 기능에 초점을 맞춰 RealityKit를 소개하고 사용법을 보여드리겠습니다 다른 개념을 다루거나 더욱 자세히 설명하는 세션도 언급하겠습니다 이제 시작하죠 이 프레젠테이션에서는 Hello World 경험을 사용하여 개념을 설명하겠습니다 하지만 개념을 설명하기에 앞서 이 경험의 일부인 세 가지 모듈을 소개하겠습니다 첫 번째 모듈인 Planet Earth는 자체 윈도우에 3D 지구본을 표시해서 어느 각도에서든 지구본과 상호 작용할 수 있습니다 두 번째 모듈인 Objects in Orbit은 몰입형 경험으로서 지구, 달, 인공위성을 애니메이션, 공간 음향 위성 궤도와 같은 사용자 설정 동작을 이용해 보여줍니다 세 번째 모듈인 Solar System에는 완전한 몰입형 경험이 포함되어 있습니다 자세한 내용은 다른 세션에서 확인하실 수 있습니다 SwiftUI, RealityKit와 Reality Composer Pro를 사용하여 Hello World 경험의 3D 요소를 빌드하는 방법을 소개하겠습니다 함께 보시죠 먼저 RealityKit를 SwiftUI와 함께 사용하여 한 차원 더 높은 수준으로 앱을 끌어올리는 방법을 설명하겠습니다 다음으로 RealityKit의 빌딩 블록에 대해 살펴보겠습니다 지구 모델과 같은 엔티티와 동작을 구현하는 컴포넌트에 대해 알아보죠 RealityView의 새로운 기능도 알려드립니다 3D 모델 및 효과를 위한 새로운 SwiftUI 뷰를 살펴보죠 그다음 입력을 처리하고 애니메이션과 공간 음향으로 앱을 생생하게 구현하는 방법을 알아봅니다 마지막으로 사용자 설정 컴포넌트와 시스템으로 RealityKit의 잠재력을 극대화하는 방법에 대해 이야기하겠습니다 RealityKit와 SwiftUI가 함께 작동하는 방식부터 살펴보겠습니다 SwiftUI는 뷰와 윈도우를 정의하는 방법이며 RealityKit를 사용하면 3D 요소를 추가할 수 있습니다 예를 들어 World 앱은 SwiftUI를 사용하여 몇 가지 버튼이 있는 표준 2D 윈도우를 표시합니다 왼쪽에 있는 Planet Earth 버튼을 탭하면 상세 뷰로 이동해서 지구의 2D 그림을 보여줍니다 그런데 2D 이미지를 3D 지구본으로 어떻게 바꿀까요? RealityKit의 모델 3D 뷰를 사용하면 2D 윈도우에 3D 콘텐츠를 쉽게 추가할 수 있습니다 코드를 살펴보겠습니다 여기에 지구본 이미지를 표시하는 SwiftUI 뷰가 있습니다 3D 디스플레이로 변경하기 위해 RealityKit 가져오기를 하고 이미지를 모델 3D 뷰로 변경합니다 그리고 내 프로젝트의 Globe라는 USD 파일을 참조합니다 로드된 모델을 표시하기 전에 코드 두 개를 추가하면 사용자 설정이 가능합니다 반환되는 모델에 대한 콘텐츠 클로저와 모델이 로드되는 동안 표시되는 뷰를 지정하는 플레이스홀더 뷰 빌더를 사용자 설정할 수 있습니다 콘텐츠 클로저에서 resizable과 scaledToFit 수정자를 추가해서 UI의 사용 가능한 공간에 모델이 들어갈 수 있게 합니다 그리고 Model 3D는 모델을 비동기식으로 로드하기 때문에 로드 프로세스 중에 표시되는 뷰를 사용자 설정할 수 있는 플레이스홀더 뷰 빌더가 있습니다 여기서는 내장 ProgressView를 사용하여 로딩 스피너를 표시하겠습니다 마지막으로 지구본 3D 모델을 앱 또는 Swift 패키지에 리소스로 추가해야 합니다
이제 모델이 Quick Look 또는 Reality Composer Pro에서와 동일한 형태로 앱에 바로 표시됩니다 3D 콘텐츠를 2D 윈도우에 배치하는 것도 좋지만 저는 3D 모델을 전면 중앙에 배치하고 싶습니다 그렇게 하기 위해서 지구본을 별도의 윈도우에 배치하겠습니다 앱의 상세 뷰에 새 윈도우를 여는 버튼을 추가하고요 그리고 2D 배경에 콘텐츠를 표시하는 일반 윈도우 대신에 입체 볼륨에 콘텐츠를 배치하는 새로운 윈도우 스타일을 사용하겠습니다 이러한 윈도우를 '볼류메트릭 윈도우'이라고 합니다 3D 콘텐츠를 보는 데 적합한 윈도우죠 2D 윈도우와 달리 볼류메트릭 윈도우는 모든 각도에서 사용할 수 있어서 3D 모델을 표시하기에 이상적입니다 또한 볼류메트릭 윈도우는 실물과 동일한 고정 크기를 항상 유지합니다 볼류메트릭 윈도우에서 모델 크기를 1m로 조정하면 모델 크기는 항상 1m로 동일하게 표시됩니다 Hello World 앱의 지구본에 적합한 윈도우죠 볼류메트릭 윈도우를 추가하는 과정을 살펴보겠습니다 먼저 앱에 window group을 추가하겠습니다 window group은 앱이 새 윈도우를 여는 데 사용할 수 있는 템플릿 역할을 합니다 앱의 메인 윈도우와 구분할 수 있도록 새 윈도우에 식별자를 부여하겠습니다 다음으로 windowStyle volumetric 수정자를 window group에 추가합니다 그리고 defaultSize 수정자를 추가해서 윈도우의 크기를 미터 단위로 지정합니다 마지막으로 상세 뷰에 버튼을 추가하겠습니다 방금 추가한 윈도우를 이 버튼으로 열기 위해서 SwiftUI 환경으로부터 윈도우 열기 동작에 액세스 가능한 프로퍼티를 추가하겠습니다
그런 다음에 내 버튼에서 윈도우 열기 동작을 호출합니다
시뮬레이터에서 이 앱을 실행해 보겠습니다 '지구본 보기' 버튼을 누르면 볼류메트릭 윈도우가 나타납니다 이제 전면뿐만 아니라 여러 각도에서 지구본과 상호 작용 할 수 있습니다
생생한 경험을 구현하려면 몰입감이 중요할 때가 있습니다 World 앱의 Objects in Orbit 모듈에서 지구와 인공위성 궤도를 애니메이션으로 보여주면 몰입을 유도할 수 있습니다 여기에서는 새로운 scene 유형의 몰입형 공간을 사용합니다 이 공간에서는 앱이 어디에나 3D 요소를 배치할 수 있습니다 Immersive Space를 열면 앱이 윈도우의 경계를 넘어 마법과도 같은 경험을 제공할 수 있습니다 Immersive Space를 추가하는 것은 window group을 추가하는 것과 비슷합니다 이것은 앱 본문의 새로운 scene입니다 여기에서는 RealityView를 사용합니다 Model 3D보다 scene을 더욱 잘 제어할 수 있죠 잠시 뒤에 RealityView에 대해 자세히 살펴보겠습니다 앞에서와 같이 앱의 상세 뷰에 버튼을 추가하겠습니다 환경에서 openImmersiveSpace 동작을 가져와 제가 정의한 scene의 식별자로 해당 동작을 호출합니다
openImmersiveSpace 동작은 비동기식이란 점에 유의하세요 공간이 열리고 나면 해당 동작이 완료됩니다 '궤도 보기' 버튼을 누르면 Immersive Space가 나타납니다 이 정도만으로도 훌륭하지만 더욱 매력적으로 만들 수 있습니다 RealityKit로 상호 작용과 애니메이션 오디오를 추가하면 더욱 멋진 공간이 됩니다 3D 콘텐츠가 포함된 2D 윈도우로 작업하든 3D 모델을 강조하는 볼류메트릭 윈도우로 작업하든 여기 나오는 SwiftUI 세션을 아직 확인하지 않으셨다면 확인해 보시기 바랍니다 '공간 컴퓨팅을 위한 SwiftUI 알아보기'에서는 이 플랫폼에서 사용할 수 있는 SwiftUI의 새 기능을 알아봅니다 'SwiftUI 한 차원 높이기'에서는 윈도우에서 3D 콘텐츠를 최대한 활용하는 법을 보여줍니다 몰입에도 여러 스타일이 있습니다 Hello World 앱의 태양계 모듈이 사용하는 완전 몰입형 공간은 passthrough를 숨기고 자체 배경을 표시합니다 'SwiftUI와 함께 윈도우 너머로' 세션에서는 몰입형 공간의 모든 스타일을 자세히 설명합니다 몰입형 경험을 빌드하려면 이 영상을 꼭 확인해 보시기를 추천합니다 SwiftUI 뷰에서 RealityKit를 사용하는 두 가지 방법을 살펴봤습니다 사용하기 쉬운 Model 3D와 RealityView를 알아봤죠 남은 세션에서 RealityView를 또 다루겠습니다 RealityKit 엔티티를 사용하는 3D 콘텐츠를 RealityView로 만들 수 있기 때문입니다 그렇다면 RealityKit 엔티티는 무엇일까요? 엔티티는 컨테이너 객체입니다 코드에서 빈 엔티티를 만들면 아무 작업도 수행되지 않습니다 엔티티가 렌더링하거나 동작을 제공하도록 만들려면 엔티티에 컴포넌트가 있어야 합니다 컴포넌트 각각은 엔티티에서 특정 동작을 활성화합니다 예를 들어보겠습니다 이 앱의 지구 엔티티는 두 가지 컴포넌트로 구현됩니다 엔티티에 메시와 머티리얼을 제공하는 모델 컴포넌트와 엔티티를 3D 공간에 배치하는 트랜스폼 컴포넌트죠 위성 엔티티도 마찬가지입니다 모델 컴포넌트는 메시를 렌더링하고 메시에 머티리얼을 적용합니다 이러한 지구와 위성 모델은 디지털 콘텐츠 제작 도구로 만들어졌으며 USDZ 파일로 내보내기 되어 RealityKit에 로드됐습니다 이러한 메시에는 물리 기반 머티리얼이 적용되어 최종 형태가 표시됩니다 머티리얼은 텍스처와 셰이더 세트를 사용해 메시 표면이 빛에 반응하는 방식을 표현합니다 머티리얼에 대해 자세히 알아보려면 닐스의 세션인 'Reality Composer Pro의 머티리얼 살펴보기'를 시청하세요 모델 컴포넌트 외에도 이러한 엔티티에는 트랜스폼 컴포넌트가 있습니다 트랜스폼 컴포넌트는 3D 공간에 엔티티를 배치합니다 엔티티의 위치, 방향, 배율을 제어하려면 트랜스폼 컴포넌트의 프로퍼티를 설정하고 엔티티의 부모를 설정하면 됩니다 RealityKit는 ARKit나 다른 여러 3D 엔진과 동일한 3D 좌표 규칙을 사용합니다 원점은 RealityView의 중심에 있습니다 Y축은 위를 향하고 Z축은 여러분을 향하며 X축은 오른쪽을 향합니다 단위는 1m입니다 이러한 좌표 규칙은 SwiftUI의 좌표 규칙과 다르다는 점에 유의하세요 RealityView의 콘텐츠 인스턴스에는 RealityKit의 좌표 공간과 SwiftUI의 좌표 공간을 서로 쉽게 변환할 수 있는 함수가 있습니다 모든 엔티티에는 트랜스폼 컴포넌트가 있지만 모델 컴포넌트는 없을 수도 있습니다 경우에 따라 엔티티는 여러 자식 엔티티로 구성되며 자식 엔티티에는 저마다 컴포넌트 세트가 있습니다 그래서 프로그래밍 방식으로 엔티티를 제어할 수 있죠 예를 들어 자식 엔티티의 트랜스폼 컴포넌트에서 개별 애니메이션을 재생할 수 있습니다 RealityKit에는 수행하려는 작업에 따라 다양한 컴포넌트가 포함되어 있습니다 오늘은 구체적인 컴포넌트를 몇 가지 설명하겠습니다 충돌, 입력 타깃 호버 이펙트 컴포넌트를 포함해서요 또한 자신만의 컴포넌트를 만드는 방법도 보여 드리겠습니다 엔티티, 컴포넌트의 작동 방식을 살펴봤으니 이제 RealityView를 사용해서 이러한 엔티티를 앱에 배치해 보겠습니다 RealityView는 SwiftUI 뷰로 엔티티를 몇 개든지 포함할 수 있습니다 엔티티를 RealityView에 포함시켜야만 렌더링, 애니메이션과 시뮬레이션이 가능합니다 그렇다면 RealityView는 어떻게 작동할까요? RealityView는 뷰에 엔티티를 추가할 수 있는 콘텐츠 인스턴스를 제공합니다 엔티티를 이미 로드했거나 프로그래밍 방식으로 엔티티를 생성하려는 경우에 시작할 수 있는 쉬운 방법입니다 하지만 이 클로저는 비동기식이라서 간단하게 파일로부터 엔티티를 로드하여 뷰에 엔티티를 표시할 수 있습니다 여기서는 지구 모델을 USD 파일로부터 비동기식으로 로드하고 로드가 완료되고 나면 지구 모델을 콘텐츠 인스턴스에 추가합니다 또한 모델을 두 개 이상 로드하고 두 모델을 모두 RealityView에 배치할 수 있습니다 두 모델은 나란히 배치되는 대신에 같은 공간을 차지합니다 이러한 배치를 원치 않는다면 뷰에 추가된 엔티티의 위치를 변경할 수 있습니다 이 예에서는 달 엔티티를 오른쪽으로 0.5m 위치에 배치합니다 RealityView를 설정하고 나면 RealityKit 컴포넌트에 저장된 프로퍼티에 앱의 상태를 연결하고 싶을 수 있습니다 RealityView를 사용하면 SwiftUI로 관리하는 상태와 엔티티 사이의 연결을 업데이트 클로저를 통해 표현할 수 있습니다 이렇게 하면 앱의 데이터 모델에서 진실 공급원을 사용해 3D 모델의 동작을 쉽게 구동할 수 있습니다 이 뷰는 모델을 로드하고 뷰를 사용하는 사람이 제어하는 회전을 적용합니다 업데이트 섹션의 코드는 종속된 값이 변경될 때만 실행된다는 점에 유의하세요 2D와 3D 요소가 결합한 UI를 구축하는 경우 뷰와 엔티티 사이에서 좌표를 변환해야 하는 경우가 있습니다 RealityView는 좌표 변환 함수를 제공해서 SwiftUI 뷰의 좌표 공간과 RealityKit 엔티티의 좌표 공간을 서로 변환할 수 있게 합니다 RealityView의 콘텐츠 인스턴스는 포인트와 바운딩 박스를 변환하고 SwiftUI의 좌표 공간에서 엔티티의 로컬 공간으로 또는 그 반대로 변환하는 변환 함수를 제공합니다 여기에서는 뷰 치수 중에서 최소 길이를 가져오고 사용 가능한 공간에 맞게 로드된 엔티티의 크기를 조정합니다 RealityView는 엔티티와 컴포넌트가 발행한 이벤트를 구독하는 메커니즘도 제공합니다 이 예에서는 로드가 완료된 뒤에 로드된 USD 파일에서 생성된 애니메이션을 재생합니다 콘텐츠 인스턴스에는 subscribe to: 함수가 있습니다 이 함수는 이벤트 핸들러를 추가하죠 이 예시는 애니메이션이 완료될 때 몇 가지 코드를 실행합니다 애니메이션부터 물리와 오디오까지 온갖 종류에 대해 발행된 RealityKit 이벤트가 있습니다 엔티티에 SwiftUI 뷰를 추가할 수도 있습니다 RealityView의 어태치먼트 기능을 사용하면 3D 공간에서 뷰를 쉽게 배치할 수 있습니다 유진의 세션 'RealityKit로 공간 컴퓨팅 앱 강화하기'에서 자세한 내용을 살펴보세요 RealityView로는 많은 일을 할 수 있습니다 하지만 천체를 생생히 구현하는 일로 다시 돌아가 보겠습니다 먼저 드래그 제스처를 추가해서 지구 엔티티의 위치를 변경하는 방법을 살펴보겠습니다 그다음 애니메이션과 공간 음향을 설명하겠습니다 다음은 엔티티 세 개가 포함된 RealityView의 예입니다 다른 SwiftUI 뷰와 마찬가지로 RealityView에 제스처를 추가할 수 있으며 해당 뷰의 엔티티에 대해 적중 테스트를 수행할 것입니다 입력을 받으려면 엔티티에 입력 타깃 컴포넌트와 충돌 컴포넌트가 모두 있어야 합니다 터치 이벤트가 RealityView에서 처리될 때 충돌 컴포넌트와 입력 타깃 컴포넌트 중에 하나라도 없는 엔티티는 무시됩니다 마지막 엔티티에만 두 컴포넌트가 모두 있기 때문에 이 RealityView에 추가된 제스처는 마지막 엔티티에 대한 입력에만 반응합니다 지구 엔티티를 드래그할 수 있게 만들기 위해서 입력 타깃 컴포넌트와 충돌 컴포넌트를 제공하고 드래그 제스처를 RealityView에 추가하겠습니다 Reality Composer Pro를 사용해 컴포넌트를 추가하겠습니다 Reality Composer Pro는 새로운 개발자 도구로서 3D 콘텐츠를 구성하고 편집하며 미리보기 할 수 있습니다 저는 엔티티에 몇 가지 컴포넌트를 추가하는 데만 사용하겠습니다 Reality Composer Pro로 가능한 작업에 대해 알아보려면 에릭의 세션 'Reality Composer Pro 알아보기'를 확인하세요 World 앱에는 이 경험에서 사용하는 USD 파일이 포함된 World Assets 패키지가 이미 설정되어 있습니다 Reality Composer Pro에서 해당 패키지를 열겠습니다
지구 모델은 USDZ 아카이브에 있습니다 이 아카이브는 self-contained이며 수정할 수 없습니다 해당 에셋을 수정하는 대신 새로운 USD scene 파일을 생성해 지구 에셋을 참조하겠습니다 USD 파일은 다른 USD 참조가 가능하며, 참조한 USD 파일을 현재 위치에서 변경 없이 수정할 수 있습니다 이렇게 비파괴적인 편집은 다른 사람이 작업하고 있는 USD 파일을 약간 변경해야 할 때 정말 편리합니다 DraggableGlobe라는 새로운 scene을 만들고 지구본 파일을 드래그하여 참조를 생성합니다
이제 컴포넌트를 추가할 수 있습니다 이제 입력 타깃 컴포넌트와 충돌 컴포넌트를 추가하겠습니다 충돌 컴포넌트의 기본 모양은 정육면체입니다 모델에 더 적합하도록 구형으로 변경하겠습니다 충돌 모양이 시각적 모델과 적절하게 비슷한 것이 중요합니다 둘이 비슷할수록 모델과 더욱 직관적으로 상호 작용할 수 있습니다 지구 모델을 움직이고 싶기 때문에 RealityView에 드래그 제스처를 추가하겠습니다 표준 SwiftUI 드래그 제스처가 작동하긴 하겠지만 전체 뷰가 아닌 특정 엔티티를 조작하는 제스처를 활성화할 수 있습니다 제스처에 targetToEntity 수정자를 추가하면 되죠 제스처값이 변경될 때 엔티티의 위치가 일치하도록 변경하겠습니다 그런데 매우 중요한 일이 한 가지 있습니다 제스처값이 SwiftUI의 좌표 공간에 있어서 RealityKit의 좌표 공간으로 변환해야만 엔티티의 위치를 변경할 수 있습니다 이제 모든 부분이 준비됐습니다 그래서 Objects in Orbit 모듈에서 핀치 및 드래그하여 지구를 움직일 수 있습니다 좋습니다 앱이 상호 작용형으로 바뀌었네요 그런데 지구 엔티티가 상호 작용형이라는 것을 표시하고 싶습니다 이것을 표시하는 데 사용하는 RealityKit 컴포넌트가 있습니다 HoverEffectComponent죠 SwiftUI와 RealityKit에서 제공하는 호버 이펙트는 여러분이 보는 위치에서 앱이 반응하도록 하는 유일한 방법입니다 이 효과는 개인 정보를 보호하기 위해서 앱 프로세스 외부에서 적용됩니다 RealityView에 추가된 지구 엔티티에 호버 이펙트 컴포넌트를 추가하겠습니다 이제 커서가 위에 있을 때 지구 모델이 밝아집니다 모델과 상호 작용 할 수 있다는 정보를 알려주죠 다음은 애니메이션으로 넘어가겠습니다 RealityKit에는 다양한 내장 애니메이션 유형이 있습니다 예를 들어 from-to-by 애니메이션은 프로퍼티를 초기 값부터 최종 값까지 애니메이션화합니다 orbit 애니메이션은 중심 주변에서 엔티티가 돌아가게 하며 time-sampled 애니메이션은 일련의 값에 따라 프레임 단위로 진행됩니다 orbit 애니메이션을 달에 적용해 보겠습니다 달이 궤도를 한 바퀴 도는 데 30초가 걸릴 것이며 궤도 축은 Y축이 됩니다 그리고 궤도가 달의 현재 위치부터 시작되도록 합니다 orbit 애니메이션의 프로퍼티를 정의하고 나면 애니메이션 리소스를 생성하고 달 엔티티에서 orbit 애니메이션을 재생합니다 이제 달이 지구를 중심으로 공전합니다 저는 이 순간이 마법처럼 느껴집니다 애니메이션을 적용하니까 scene이 살아있는 듯하죠 3D 콘텐츠에 생동감을 불어넣는 데 애니메이션이 도움이 된다면 Spatial Audio는 모델이 실존하는 것처럼 느끼게 해줍니다 RealityKit에는 오디오 유형이 세 가지 있습니다 spatial, ambient, channel 유형이 있죠 각각에 대해 자세히 살펴보겠습니다 RealityKit 사운드는 기본적으로 공간 음향이라서 오디오 소스가 주변에 실존하는 것처럼 소리가 들립니다 Spatial Audio 컴포넌트를 쓰면 객체가 공간에서 소리 내는 방식을 사용자 설정하여 객체를 더욱 사실적으로 만들 수 있습니다 더욱 예술적으로도 만들 수 있죠 지향성을 사용해 모든 방향으로 소리를 내거나 특정 방향으로 소리를 낼 수 있습니다 Ambient Audio 컴포넌트는 주변 환경의 사운드를 표현하는 멀티채널 파일에 적합합니다 ambient 소스에는 별도의 리버브가 추가되지 않으며 주변의 고정된 방향에서 각 채널이 재생됩니다 마지막으로 Channel Audio 컴포넌트는 오디오 파일 채널을 아무런 공간 효과 없이 직접 스피커로 내보냅니다 시각적 요소와 연결되지 않은 배경 음악에 적합한 컴포넌트입니다 Reality Composer Pro에서 scene에 오디오를 추가하고 RealityKit를 사용해 오디오를 인터페이스와 연결할 수 있습니다 아니면 코드에서 오디오를 연결할 수도 있죠 한번 보겠습니다 궤도를 도는 인공위성에 반복되는 소리를 좀 더하겠습니다 먼저 오디오 소스 역할을 할 빈 엔티티에 Spatial Audio 컴포넌트를 추가하겠습니다 지향성이 0.75면 특정 방향으로 집중된 음파를 생성합니다 오디오 소스 엔티티를 Y축 중심으로 회전시켜 원하는 방향으로 소리가 나도록 하겠습니다 그다음 리소스로부터 반복 오디오 클립을 로드하고 playAudio를 호출하여 audioSource 엔티티에서 재생합니다 실제 어떻게 작동하는지 보죠 Spatial Audio 소스는 특정 방향으로 소리가 집중되도록 설정되어 위성이 관찰자 쪽에 있으면 소리가 선명하지만 지구 반대편에 있으면 소리가 작아집니다 이제까지 입력, 애니메이션 오디오 컴포넌트를 살펴봤습니다 RealityKit의 기존 기능을 다양한 방식으로 결합하면 더 많은 기능을 구축할 수 있습니다 이 목적을 위해 사용할 수 있는 중요한 도구가 두 가지 있습니다 컴포넌트와 시스템을 정의할 수 있는 도구죠 컴포넌트에는 3D 경험의 한 측면을 제어하는 데이터가 포함되어 있습니다 컴포넌트가 모여 엔티티가 됩니다 컴포넌트가 없는 엔티티는 아무런 작업도 수행하지 않습니다 컴포넌트 각각은 엔티티 구현에 한 가지 요소를 제공합니다 트랜스폼 컴포넌트가 엔티티의 위치를 지정하고 모델 컴포넌트는 3D 모델을 렌더링한다는 것을 배웠습니다 RealityKit에서 제공하는 미리 정의된 컴포넌트 외에도 자신만의 컴포넌트를 정의할 수 있습니다 다음은 사용자 지정 컴포넌트의 예입니다 traceMesh 객체를 포함하는 컴포넌트로 제 동료 폴이 만들었죠 trace 컴포넌트 유형은 컴포넌트 프로토콜을 준수합니다 따라서 런타임 시 어느 엔티티에서든지 이 컴포넌트를 가져와서 설정할 수 있습니다 데이터 기반 워크플로를 도입할 수도 있습니다 Swift 패키지에서 컴포넌트를 정의하고 컴포넌트가 Codable 프로토콜을 준수하게 하면 됩니다 Codable 컴포넌트는 Reality Composer Pro 인터페이스에 나타날 것이며 코드를 작성하는 디자인 타임에 엔티티에 직접 추가할 수 있습니다 사용자 지정 컴포넌트에 대해 더욱 자세히 알아보려면 'Xcode로 Reality Composer Pro 콘텐츠 작업하기'를 확인해 보세요 이 영상의 앞부분에서 엔티티를 살펴봤으며 컴포넌트에 대해서는 방금 설명했습니다 다음으로 시스템에 대해 이야기하겠습니다 시스템에는 엔티티와 컴포넌트에 작용하는 코드가 포함돼 있습니다 엔티티, 컴포넌트, 시스템 약자로 ECS는 3D 경험의 형태와 동작을 모델링하기 위한 도구입니다 시스템은 앱의 동작을 구현하는 코드를 구조화하는 방법입니다 시스템의 코드는 일정한 간격으로 실행되어 컴포넌트의 현재 상태에 따라 작동합니다 예를 들어 여기서 TraceSystem은 위성 엔티티가 공전할 때 위성 궤도를 따라가는 라인 메시를 업데이트합니다 업데이트할 때마다 엔티티의 현재 위치가 트레이스에 추가되죠 시스템이 등록되고 나면 여러분의 앱에서 RealityKit를 사용하는 모든 곳에 시스템이 자동으로 적용됩니다 앱의 이니셜라이저에 trace 시스템을 등록하면 관련된 모든 엔티티에 대하여 trace 시스템이 업데이트됩니다 그런데 어떤 엔티티가 관련 있고 시스템은 언제 업데이트될까요? 이 시스템이 업데이트하려는 건 trace 컴포넌트 있는 엔티티뿐이니 저는 trace 컴포넌트가 있는 엔티티로 필터링하는 엔티티 쿼리를 만듭니다 업데이트 함수에서 시스템은 엔티티 쿼리를 전달하고 렌더링할 때 엔티티를 업데이트하도록 지정합니다 여기서 렌더링 조건은 부드러운 애니메이션을 위해 시스템이 적절한 속도로 업데이트된다는 의미입니다 다음은 trace 시스템이 작동하는 모습입니다 사용자 지정 애니메이션이 부드럽게 움직이도록 trace 시스템은 엔티티 위치를 라인 메시에 추가하죠 시스템은 다양한 효과와 동작을 구현하는 데 정말 효과적인 방법입니다 RealityKit에는 3D 앱을 쉽게 구축할 수 있는 기능이 많습니다 RealityKit와 RealityView를 쓰면 SwiftUI로 정의된 뷰, 윈도우, 몰입형 공간에 3D 요소를 더할 수 있습니다 RealityKit를 이용하면 USD 파일을 로드하고 제스처를 처리하며 애니메이션과 공간 음향을 재생할 수 있습니다 RealityKit는 미리 정의된 컴포넌트를 많이 제공하지만 앱에 따라 필요한 요구에 맞게 사용자 지정 컴포넌트 및 시스템을 여러분이 직접 정의할 수도 있습니다 RealityKit를 시작하는 데 필요한 개념을 지금까지 살펴보았습니다 유진의 세션 'RealityKit로 공간 컴퓨팅 앱 강화하기'에서는 RealityKit의 더 많은 기능을 설명해 드립니다 포털, 파티클 이미터 어태치먼트와 같은 기능을 다루죠 어맨다의 세션 'Xcode로 Reality Composer Pro 콘텐츠 작업하기'에서는 Reality Composer Pro와 RealityKit Xcode previews 시뮬레이터를 사용하여 몰입형 앱을 빌드하는 과정을 안내합니다 RealityKit에는 앱에서 사용할 수 있는 흥미로운 기능이 많습니다 여러분이 어떤 멋진 경험을 만들어 낼지 기대가 되네요 시청해 주셔서 감사합니다 ♪
-
-
3:40 - Model3D
import SwiftUI import RealityKit struct GlobeModule: View { var body: some View { Model3D(named: "Globe") { model in model .resizable() .scaledToFit() } placeholder: { ProgressView() } } }
-
5:52 - Volumetric window
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) } }
-
7:31 - ImmersiveSpace
import SwiftUI import RealityKit // Define a immersive space. struct WorldApp: App { var body: some SwiftUI.Scene { // ... ImmersiveSpace(id: "objects-in-orbit") { RealityView { content in // ... } } } }
-
12:40 - RealityView
import SwiftUI import RealityKit struct Orbit: View { let earth: Entity var body: some View { RealityView { content in content.add(earth) } } }
-
12:54 - RealityView asynchronous loading and entity positioning
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] } } } }
-
13:54 - Earth rotation
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) } } }
-
14:27 - Converting co-ordinate spaces
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] } } } } }
-
14:56 - Play an animation
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) { // ... } } } }
-
18:31 - Adding a drag gesture
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!) }) } }
-
20:20 - Playing a transform animation
// 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) }
-
22:12 - Adding audio
// 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) }
-
23:47 - Defining a custom component
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 = "" }
-
24:51 - Defining a system
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() } }
-
-
찾고 계신 콘텐츠가 있나요? 위에 주제를 입력하고 원하는 내용을 바로 검색해 보세요.
쿼리를 제출하는 중에 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.