
-
RealityKit의 새로운 기능
iOS, iPadOS, macOS, tvOS 및 visionOS에 대한 풍성한 3D 콘텐츠를 구축하는 데 도움이 되는 새로운 RealityKit 기능으로 창의력을 발휘하세요. RealityKit을 통해 ARKit 데이터에 직접 액세스하는 방법을 학습하고 개체 조작 기능을 사용하여 3D 콘텐츠와 더욱 자연스럽게 상호작용할 수 있는 방법을 알아볼 수 있습니다. 상호작용 샘플을 사용하여 장면 이해, 환경 블렌딩 및 인스턴싱 등을 위한 새로운 API를 알아보세요.
챕터
- 0:00 - 서론
- 3:19 - 업데이트 고정하기
- 6:52 - ManipulationComponent
- 10:01 - 장면 이해
- 11:18 - EnvironmentBlendingComponent
- 12:26 - MeshInstancesComponent
- 16:28 - 몰입형 미디어
- 21:43 - 액세서리 및 기타 정보
리소스
관련 비디오
WWDC25
-
비디오 검색…
안녕하세요, 저는 RealityKit 팀의 소프트웨어 엔지니어 Laurence이며 “RealityKit의 새로운 기능” 세션에 오신 것을 환영합니다 이 세션에서는 올해 릴리즈되는 새로운 RealityKit 기능을 설명합니다
2019년에 출시된 RealityKit으로 3D 콘텐츠를 앱에 통합해 사실적인 렌더링을 구현하고 몰입형 경험을 향상할 수 있었는데요 이후 Apple은 여러분의 수많은 피드백을 받아 매년 이 프레임을 발전시켰습니다 RealityKit의 다양한 기능을 사용하면 3D 콘텐츠가 현실 환경과 완벽히 융화되므로 visionOS에서 몰입형 앱과 게임을 만들 수 있습니다 RealityKit의 주요 기능 대다수는 visionOS 외에 iOS, iPadOS와 macOS에서도 사용 가능합니다 RealityKit의 크로스 플랫폼 기능으로는 앱을 한 번 작성한 후 최소한의 코드 변경으로 다양한 플랫폼으로 가져올 수 있습니다 올해부터 RealityKit은 최신 tvOS에서도 지원됩니다 이제 기존 앱 및 경험을 AppleTV로 가져오거나 더 큰 화면용으로 새로운 경험을 만들 수 있습니다 RealityKit은 모든 세대의 AppleTV 4K에서 지원됩니다 올해 RealityKit 업데이트의 여러 새로운 기능을 통해 가상과 현실을 융합한 3D 경험을 매우 쉽게 만들 수 있습니다 이 세션에서는 이러한 기능 중 일부를 소개합니다 ManipulationComponent EnvironmentBlendingComponent MeshInstancesComponent 등입니다 그중 일부 기능을 사용해 공간 퍼즐 게임을 만들어 보겠습니다 게임을 시작하면 앞의 표면에 고정된 잠긴 상자가 있습니다 상자 주변에는 상호작용 가능한 여러 객체가 있습니다 이러한 객체 중 하나의 밑에 상자를 여는 열쇠가 붙어 있습니다 객체를 잡고 조사하면 어느 것에 열쇠가 있는지 알아낼 수 있습니다 열쇠를 얻으면 상자를 열고 보상을 확인할 수 있습니다
바로 작은 불꽃놀이입니다
먼저 RealityKit의 새 네이티브 ARKit 지원을 사용해 플레이어 앞 공간에 모델을 고정하고 앵커 라이프사이클 변경을 처리합니다 새 ManipulationComponent로 장면의 3D 엔티티에 상호작용을 추가하는 방법을 보여 드리죠 PhysicsBodyComponent도 사용해 놓았을 때 현실적으로 떨어지도록 합니다 그런 다음 새 SceneUnderstanding API를 사용해 게임 엔티티가 장면 이해 메시와 충돌하도록 합니다
이후 EnvironmentBlendingComponent를 사용해 앱이 현실과 잘 융화되도록 합니다
또 새 MeshInstancesComponent로 장면을 장식할 3D 모델의 인스턴스 여러 개를 효율적으로 그리는 방법을 설명하겠습니다 그리고 새로운 몰입형 미디어 업데이트를 살펴보겠습니다 공간 액세서리, 엔티티 업데이트와 같이 다른 새로운 발표 내용도 다룹니다 먼저 RealityKit을 통해 ARKit 데이터에 직접 접근 가능한 새 API를 사용하여 3D 모델을 실제 환경에 고정하는 것을 보죠 RealityKit AnchorEntity를 사용해 테이블에 게임을 배치합니다 앵커 엔티티는 가상 콘텐츠를 현실 표면에 연결하는 데 사용합니다 올해 ARKit 고정 데이터를 직접 노출하는 방식으로 AnchorEntity가 더 강력해졌습니다 방법을 보여 드리겠습니다 RealityKit을 통해 ARKit 데이터에 직접 접근하려면 먼저 SpatialTrackingSession을 만들어야 합니다 세션의 구성은 AnchorEntity 상태가 변경되면 앱에 새 AnchorStateEvents를 보낼 것을 RealityKit에 지시합니다 그런 다음 AnchorEntity를 설정해 찾고 있는 앵커의 속성을 필터링할 수 있습니다 앱에서 특정 치수의 테이블을 찾고 싶습니다 RealityKit이 제가 AnchorEntity에 설정한 속성과 일치하는 최적의 앵커를 찾으면 AnchorStateEvent를 발생시킵니다 이 AnchorStateEvent 인스턴스에는 앵커의 변환 및 범위 등 게임 배치에 사용할 수 있는 ARKit 데이터가 있습니다 코드에서 살펴보겠습니다 먼저 RealityKit AnchorEntity가 환경에 추적될 수 있도록 하는 SpatialTrackingSession을 생성합니다 게임에서 보물 상자가 생성되는 평면을 추적해야 하므로 SpatialTrackingSession 구성을 평면 추적을 활성화해 설정하죠
이제 방금 만든 구성을 실행해 세션을 추적할 수 있습니다 그리고 테이블에 게임을 배치할 수 있는 AnchorEntity를 생성합니다 AnchorEntity를 수평면이고 연결된 최소 경계가 15cm²인 테이블로 분류합니다 이 AnchorEntity는 미고정 상태로 시작되지만 제공된 분류 및 경계와 일치하는 테이블 평면이 감지되면 고정됩니다 앵커 상태가 변경될 때 업데이트를 받으려면 새 AnchorStateEvents API를 사용해야 합니다
AnchorStateEvents API를 사용하면 엔티티가 고정되었을 때 고정이 해제되려고 할 때 고정에 실패했을 때에 대한 이벤트를 구독할 수 있습니다 앱에서 DidAnchor 이벤트를 사용해 테이블 표면의 경계 안에 게임 엔티티를 배치하겠습니다
앵커 엔티티가 환경에 정상 연결되었을 때 알기 위해 코드에 DidAnchor 이벤트 구독을 추가했습니다 이벤트 구조는 새 ARKitAnchorComponent를 포함하도록 업데이트된 앵커 엔티티를 제공합니다 이 컴포넌트는 고정된 표면에 게임 엔티티를 배치하는 데 사용 가능한 범위 및 변환 등의 ARKit 데이터를 보유합니다 ARKitAnchorComponent의 앵커 속성을 활용해 이 데이터에 접근할 수 있습니다
앵커 속성을 사용하려면 ARKit 앵커 유형에 캐스팅해야 합니다 여기서는 PlaneAnchor에 캐스팅할 것인데 AnchorEntity가 평면을 찾도록 설정되어 있기 때문입니다
이제 앵커의 원시 ARKit 범위 및 변환에 접근할 수 있습니다 ARKit 변환, 특히 originFromAnchorTransform과 anchorFromExtentTransform을 사용해 게임을 배치하고 고정된 표면의 중앙에 있도록 하겠습니다 이제 몰입형 공간을 열면 적합한 표면이 발견되었을 때 게임 객체가 생성됩니다
다음으로 RealityKit의 새 ManipulationComponent를 사용해 장면에 상호작용을 추가합니다 ManipulationComponent는 장면의 3D 엔티티를 집어 회전하는 과정을 간소화합니다 손을 바꾸는 등의 고급 제스처도 지원합니다
ManipulationComponent를 사용해 플레이어가 게임 객체를 잡고 회전하여 밑의 키를 찾을 수 있도록 합니다 게임에 이 기능을 추가하는 방법을 보여 드리겠습니다 ManipulationComponent의 작동 방식과 용도에 대한 자세한 내용은 “함께하면 더욱 탁월한 SwiftUI 및 RealityKit” 세션을 참고하세요 엔티티를 집어 상호작용하려면 ManipulationComponent configureEntity 함수를 호출하면 됩니다 이 함수는 필요한 InputTarget Collision, HoverEffect Manipulation 컴포넌트를 엔티티에 자동 추가합니다 끝났습니다 이제 손으로 엔티티를 집어 회전할 수 있습니다 객체를 놓으면 원래 위치로 부드럽게 돌아가는 애니메이션이 보이는데요
코드로 돌아가서 ManipulationComponent의 `releaseBehavior` 속성을 stay로 설정합니다
이 manipulationComponent 인스턴스를 엔티티에 할당합니다 그러면 객체를 놓아도 자동으로 시작 위치로 돌아가는 애니메이션이 나오지 않습니다 대신 정지 상태를 유지합니다 다음으로 객체를 바닥에 떨어뜨리겠습니다 이를 위해 엔티티에 PhysicsBodyComponent를 추가하죠 객체를 핀치하거나 집지 않았을 때만 PhysicsBodyComponent에 중력을 활성화하고 싶습니다 새 ManipulationEvents API를 사용하면 쉽습니다
ManipulationEvents는 엔티티가 상호작용 중 겪는 다양한 상호작용 상태를 설명하는 이벤트로서 RealityKit이 발생시킵니다
예를 들어 WillRelease 이벤트는 플레이어가 엔티티를 놓으면 트리거됩니다 마찬가지로 WillBegin, WillEnd DidUpdateTransform, DidHandOff 같은 이벤트도 있습니다 developer.apple.com/kr의 설명서에서 자세히 확인하세요
게임 엔티티가 상호작용 중이 아닐 때만 중력에 반응하도록 WillBegin, WillEnd 이벤트를 사용하겠습니다
먼저 WillBegin 이벤트에 구독을 추가해 physicsBodyComponent 모드를 kinematic으로 변경하여 객체 이동 중에 물리 시스템이 개입하지 않도록 합니다 이렇게 하면 중력이 해당 객체에 영향을 미치지 않습니다
다음으로 WillEnd 이벤트에 구독을 추가해 physicsBodyComponent 모드를 다시 dynamic으로 변경합니다 해당 엔티티와 더 이상 상호작용하지 않으니까요 그러면 엔티티가 장면의 다른 물리적 객체에 반응할 수 있죠 중력에도 반응합니다 게임 객체가 물리에 반응하게 되었고 이제 플레이어 주변 환경과 충돌하게 해야 합니다 새 Scene Understanding API로 방에서 앱의 물리 시뮬레이션에 메시를 추가하면 됩니다 SpatialTrackingSession API를 통해 RealityKit은 주변 환경의 메시를 생성할 수 있습니다 Scene Understanding 메시라고 하는 이 메시로 방의 현실 객체에 충돌과 물리를 추가할 수 있습니다
SpatialTrackingSession Configuration에서 SceneUnderstandingFlags를 설정해 현실 주변 환경의 장면 이해 메시를 활용할 수 있습니다
visionOS는 현재 충돌 및 물리 플래그를 지원합니다 둘 다 사용해 게임 객체가 장면 이해 메시와 충돌하도록 하겠습니다 SpatialTrackingSession Configuration에서 두 플래그를 설정한 후 실행하겠습니다
아까의 SpatialTrackingSession을 업데이트해야 하는데요 충돌 및 물리 장면 이해 플래그를 SpatialTrackingSession 구성에 추가하고 세션을 시작하면 됩니다 이제 장면 이해 메시가 게임 물리 시뮬레이션에 참여하며 게임 객체를 테이블이나 바닥에 떨어뜨리면 환경과 충돌합니다 게임이 환경과 상호작용할 수 있고 이제 환경에 시각적으로 반응하도록 하고 싶습니다 EnvironmentBlendingComponent를 사용하면 되는데요 EnvironmentBlendingComponent는 올해 RealityKit 업데이트에서 몰입형 공간 앱을 위해 준비된 새 컴포넌트입니다
이 컴포넌트로 엔티티를 정적 현실 객체로 숨길 수 있죠 이 컴포넌트가 있는 엔티티는 정적 현실 객체에 가려진 정도에 따라 부분 또는 전체가 현실감 있게 가려집니다 사람, 반려동물처럼 동적으로 움직이는 객체는 이 컴포넌트가 있는 객체를 가리지 않습니다
이 기능을 추가하려면 EnvironmentBlendingComponent를 추가하고 선호 융화 모드를 주변 환경에 가려지는 것으로 설정하면 됩니다 EnvironmentBlendingComponent가 있는 엔티티가 현실 객체 뒤에 배치되면 이제 엔티티가 객체에 가려집니다 EnvironmentBlendingComponent를 사용하는 엔티티는 배경 환경의 일부로 취급되며 항상 장면의 다른 가상 객체 뒤에 그려집니다 EnvironmentBlendingComponent가 작동하므로 이제 새 MeshInstancesComponent를 사용해 주변 게임 영역에 장식을 추가할 수 있습니다 작년에는 LowLevelMesh LowLevelTexture API가 RealityKit에 추가되어 렌더링 데이터 제어 기능이 향상되었죠 올해 RealityKit 업데이트에서는 이 낮은 수준 접근이 렌더링의 다른 측면인 인스턴스화로 확장됩니다 앱에서 주변 공간을 장식하고 플레이 가능 영역을 정의하고 싶습니다
많은 중복 엔티티를 생성해 공간을 장식할 수 있습니다 하지만 엔티티를 여러 번 복제해야 하므로 ModelComponent 사본이 다수 생성됩니다 그러면 메모리 및 처리 공간이 많이 소모될 수 있습니다 더 효율적이고 편리한 방법은 새 MeshInstancesComponent를 사용하는 것입니다
MeshInstancesComponent를 사용하면 한 엔티티로 메시를 여러 번 그릴 수 있습니다 메시를 그릴 변환 목록만 제공하면 되죠 iOS, iPadOS, macOS, tvOS에서는 LowLevelBuffer로 렌더 데이터를 CustomMaterial에 전달 시 각 메시 인스턴스가 고유한 모습이 됩니다 MeshInstancesComponent는 편리할 뿐 아니라 GPU로 전송해야 하는 데이터를 줄여 성능을 향상할 수 있습니다 중복 메시를 그릴 때 GPU에 모델과 머티리얼의 사본을 여러 개 보내는 대신 MeshInstancesComponent가 데이터를 한 번만 보냅니다
단일 MeshInstancesComponent로 그려진 모델은 여전히 단일 엔티티의 일부로 간주됩니다 이 컴포넌트로 넓은 영역을 덮는 경우 컬링이 일어나도록 작은 엔티티 여러 개로 나누는 편이 나을 수 있습니다 코드에 MeshInstancesComponent를 사용하는 방법을 설명하겠습니다 먼저 인스턴스화할 메시입니다 앱의 콘텐츠 번들에서 엔티티를 로드해 이 메시를 준비합니다 이제 MeshInstancesComponent와 LowLevelInstanceData 객체를 초기화할 수 있습니다 LowLevelInstanceData 객체에 개별 메시 인스턴스를 위한 데이터가 담겨 있습니다 LowLevelInstanceData 객체를 생성할 때는 앱에 필요한 인스턴스 수를 제공해야 합니다 너무 혼잡하지 않은 플레이 영역 근사치를 나타내고자 20을 사용하겠습니다 다음으로 인스턴스화할 메시 부분의 인덱스에서 구독하는 MeshInstancesComponent에 LowLevelInstanceData 객체를 할당합니다 여기서는 인스턴스화할 메시가 간단하고 메시 파트가 하나이므로 LowLevelDataObject를 partIndex: 0으로 할당합니다
이제 각 메시 인스턴스의 변환으로 LowLevelInstanceData 객체를 채울 수 있습니다
장식의 다양화를 위해 각 인스턴스의 scale, angle, position을 무작위로 설정합니다 이러한 값으로 변환 행렬을 만들어 인스턴스에 할당할 수 있습니다
이제 meshInstancesComponent를 엔티티에 추가할 수 있으며 매번 MeshInstancesComponent의 데이터로 엔티티를 그리게 됩니다
이렇게 게임이 완성되었습니다
게임을 시작해 앞의 표면에 고정할 수 있고요 플레이 영역의 객체를 집고 회전해 상자의 열쇠를 찾을 수 있습니다 이 앱을 만드는 데 사용한 새 API를 정리해 보죠 새 AnchorNameEvent API로 콘텐츠를 고정했습니다 그리고 ManipulationComponent로 객체와 상호작용하게 되었고요 장면 이해 플래그로 게임 엔티티가 장면 이해 메시와 충돌하도록 했습니다 마지막으로 EnvironmentBlendingComponent와 MeshInstancesComponent로 게임이 현실과 융화되게 했습니다 이어서 새 몰입형 미디어 지원 등 올해 RealityKit에 추가될 다른 기능을 소개하겠습니다 올해 RealityKit에서 이미지를 표시하는 용도로 ImagePresentationComponent라는 새 컴포넌트가 도입됩니다 세 가지 이미지를 지원하는데요 기존 2D 이미지 및 사진 iPhone 또는 Vision Pro의 입체 사진을 말하는 공간 사진 그리고 기존 2D 이미지 또는 사진으로 만든 새로운 3D 이미지인 공간 장면입니다
공간 장면은 실제 심도가 있는 3D 이미지이며 2D 이미지로 만듭니다 일종의 사진 디오라마인데 보는 사람이 장면을 기준으로 머리를 움직일 때 모션 시차를 통해 공간 장면의 심도를 강조하죠 공간 장면은 visionOS의 사진 앱과 자체 앱에서 RealityKit을 통해 기존 2D 사진에 생동감을 불어넣기에 좋습니다 세 가지 이미지를 앱에 추가하는 코드를 살펴보겠습니다 먼저 RealityKit으로 2D 이미지 또는 사진을 표시하는 방법입니다
우선 2D 사진의 URL을 찾고 이것을 사용해 새 이미지 표시 컴포넌트를 만듭니다 컴포넌트의 이니셜라이저는 비동기인데 이미지를 메모리에 로드하는 데 잠시 시간이 걸릴 수 있어서입니다 컴포넌트가 초기화되면 엔티티에 할당해 RealityKit 장면에 표시할 수 있습니다
공간 사진을 표시하려면 한 단계가 더 필요합니다 컴포넌트를 엔티티에 설정하기 전에 원하는 보기 모드를 할당해야 합니다 원하는 보기 모드를 지정할 때는 먼저 이미지에서 지원하는지 확인해야 합니다 보기 모드를 지정하지 않거나 이미지에서 지원하지 않으면 ImagePresentationComponent가 공간 사진이라도 이미지를 2D 또는 모노스코프 보기 모드로 표시합니다 몰입형 공간 사진 표시를 설정하려면 원하는 보기 모드로 spatialStereoImmersive를 사용하면 됩니다 공간 사진으로 이미지 표시 컴포넌트를 만들 때마다 두 공간 스테레오 모드를 모두 사용할 수 있습니다 2D 이미지와 공간 사진 모두 디스크의 파일에서 로드됩니다 이러한 이미지를 공간 장면으로 표시하려면 추가 단계가 필요한데 공간 장면을 먼저 생성해야 표시할 수 있기 때문입니다 공간 장면을 생성하고 표시하는 방법을 코드로 설명하겠습니다
2D 이미지 또는 공간 사진으로 공간 장면을 생성할 수 있습니다 공간 사진으로 공간 장면을 생성하면 공간 사진의 채널 중 하나만 2D 이미지로 변환에 사용합니다 공간 장면을 생성할 때는 ImagePresentationComponent를 이미지 URL에서 직접 초기화하지 않습니다 대신 URL로 Spatial3DImage를 생성하고 공간 3D 이미지로 ImagePresentationComponent를 초기화합니다 컴포넌트가 아직 공간 장면으로 표시될 준비가 되지 않았기에 먼저 장면을 생성해야 합니다
이를 위해 공간 3D 이미지의 generate 메서드를 호출합니다 그러면 몇 초 만에 공간 장면이 생성됩니다 생성에 성공하면 ImagePresentationComponent의 availableViewingModes가 spatial3D 및 spatial3DImmersive 모드를 포함하도록 업데이트됩니다 그중 하나를 원하는 보기 모드로 설정해 공간 장면을 윈도우 또는 몰입형 방식으로 표시할 수 있습니다 공간 장면을 미리 생성할 필요는 없습니다 사진 앱에서처럼 앱 사용자가 버튼을 누를 때까지 기다릴 수도 있습니다 generate를 호출하기 전에 컴포넌트의 원하는 보기 모드를 .spatial3D로 설정하면 공간 장면을 준비와 동시에 표시하도록 컴포넌트에 알려 주는 것입니다 그러면 컴포넌트는 생성 과정에서 진행 상황 애니메이션을 표시하며 생성이 완료되면 바로 공간 장면을 표시합니다 Vision Pro에서는 이렇게 됩니다 이미지 표시 컴포넌트가 visionOS의 사진 앱과 동일한 생성 애니메이션을 표시하며 3D 결과물이 멋지게 나옵니다
정리해 보면 이렇습니다 ImagePresentationComponent로 2D 이미지, 공간 사진 공간 장면을 표시하는 다양한 방법을 표로 나타낸 것입니다 이 컴포넌트의 자세한 내용은 developer.apple.com/kr의 “RealityKit에서 이미지 표시하기” 샘플 코드를 확인하세요
다른 몰입형 미디어 업데이트는 VideoPlayerComponent가 각종 몰입형 비디오 형식 재생을 지원하도록 업데이트된 것입니다 이제 포털 및 몰입형 모드에서 전체 공간 스타일로 공간 비디오 재생을 지원합니다
180도, 360도, 광각 비디오 등의 Apple Projected Media Profile 비디오도 지원됩니다 Apple Projected Media Profile 비디오의 편의성 설정도 구성 가능한데 RealityKit이 재생을 적절히 자동 조정해 줍니다
이러한 비디오 형식과 Apple Immersive Video는 다양한 보기 모드로 재생되도록 구성할 수 있습니다 업데이트에 대한 자세한 내용은 “visionOS 앱에서 몰입형 비디오 재생 지원하기”를 확인하세요
다음으로 올해의 다른 업데이트를 설명하겠습니다 먼저 추적된 공간 액세서리를 소개합니다 SwiftUI 및 RealityKit 통합 관련 최신 업데이트를 살펴보고요 이어서 새로운 엔티티 업데이트를 확인합니다 RealityKit AVIF 텍스처 지원을 간략히 알아봅니다 그리고 새로운 호버 효과 groupID 기능을 설명합니다 마지막으로 RealityViews의 후처리 효과 추가를 살펴봅니다 그럼 시작하죠 RealityKit은 공유 공간과 전체 공간에서 앱과 상호작용할 수 있도록 하는 공간 액세서리에 대한 추적 지원을 추가하고 있습니다 6DoF로 공간 액세서리를 추적할 수 있으며 햅틱이 지원되어 앱과 게임의 상호작용을 향상할 수 있습니다 앱에 공간 액세서리 입력을 추가하는 방법은 “visionOS 세션에서 공간 액세서리 입력 살펴보기”를 시청하세요 올해 RealityKit은 더 나은 SwiftUI 통합을 위한 새로운 컴포넌트도 도입합니다 ViewAttachmentComponent를 사용하면 SwiftUI 보기를 엔티티에 직접 간단히 추가할 수 있습니다 또한 PresentationComponent로는 팝오버 등 모달 표시를 엔티티에 추가할 수 있습니다 또한 새로운 GestureComponent는 SwiftUI 제스처를 엔티티에 추가하는 과정을 간소화합니다 올해 SwiftUI 및 RealityKit 통합에 대한 자세한 내용은 “함께하면 더욱 탁월한 SwiftUI 및 RealityKit”을 확인하세요
한 엔티티를 다른 엔티티의 핀에 연결할 수 있는 새로운 엔티티 attach 메서드도 있습니다 이 API로 애니메이션화된 스켈레톤의 조인트에 메시를 매우 간단히 연결할 수 있습니다 이렇게 메시를 연결하면 수동으로 정렬할 필요가 없으며 비용이 많이 드는 계층적 변환 업데이트를 방지할 수 있습니다 메모리 Data 객체에서 엔티티를 로드할 수 있는 새로운 Entity 이니셜라이저도 있는데요 이 새로운 이니셜라이저로 온라인 소스에서 전체 RealityKit 장면 또는 USD를 로드하거나 네트워크로 스트리밍할 수 있죠 새 이니셜라이저는 기존 엔티티 이니셜라이저와 동일한 파일 형식을 지원합니다
또한 RealityKit은 AVIF 인코딩 텍스처 지원을 추가하고 있는데 10비트 색상을 지원해 품질은 jpeg와 유사하면서 크기는 대폭 줄어듭니다 Mac에서 미리보기 앱을 사용하거나 터미널에서 usdcrush를 사용하여 이 압축을 활성화해 USD를 내보낼 수 있습니다 또한 HoverEffectComponent에 GroupID라는 새 기능이 추가됩니다 GroupID는 호버 효과 간에 연관성을 만드는 방법입니다 GroupID를 공유하는 호버 효과는 활성화도 공유합니다 호버 효과에 GroupID를 할당하면 상대적 계층 구조와 관계없이 호버 효과의 활성화 방식을 완벽하게 제어할 수 있습니다 일반적으로 호버 효과는 왼쪽 예와 같이 계층적으로 적용됩니다 하위 항목 엔티티가 상위 항목 엔티티의 효과를 상속받는 거죠 하지만 오른쪽 예의 Entity A 및 Entity B처럼 엔티티에 GroupID가 있으면 효과가 하위 항목에 전파되지 않습니다
올해 또 다른 멋진 추가 내용은 RealityView의 후처리 효과 지원입니다 customPostProcessing API를 사용해 Metal Performance Shaders CIFilters 또는 자체 셰이더를 사용하는 앱에 bloom 등 맞춤형 효과를 추가할 수 있습니다 이 API는 iOS, iPadOS, macOS 및 tvOS에서 지원됩니다
올해의 RealityKit 업데이트는 RealityKit을 통한 3D 경험 생성을 용이하게 하는 것이 핵심이었죠 지금까지 새로운 RealityKit API를 사용해 게임을 환경에 고정하고 게임 피스와 상호작용하는 직관적인 방법을 확보하는 공간 퍼즐 게임을 만드는 방법을 살펴보았습니다 앱에서 RealityKit으로 공간 콘텐츠를 직접 표시할 수 있는 새로운 몰입형 미디어 업데이트도 설명했습니다
그리고 공간 액세서리 추적 엔티티 업데이트, 호버 효과 groupsID 같은 추가 업데이트를 확인했습니다 이러한 새로운 기능으로 RealityKit에서 매우 쉽게 3D 앱을 빌드할 수 있으며 여러분이 만드실 경험이 기대됩니다 시청해 주셔서 감사합니다
-
-
4:33 - Set up SpatialTrackingSession
// Set up SpatialTrackingSession @State var spatialTrackingSession = SpatialTrackingSession() RealityView { content in let configuration = SpatialTrackingSession.Configuration( tracking: [.plane] ) // Run the configuration if let unavailableCapabilities = await spatialTrackingSession.run(configuration) { // Handle errors } }
-
4:34 - Set up PlaneAnchor
// Set up PlaneAnchor RealityView { content in // Set up the SpatialTrackingSession // Add a PlaneAnchor let planeAnchor = AnchorEntity(.plane(.horizontal, classification: .table, minimumBounds: [0.15, 0.15])) content.add(planeAnchor) }
-
5:48 - Handle DidAnchor event
// Handle DidAnchor event didAnchor = content.subscribe(to: AnchorStateEvents.DidAnchor.self) { event in guard let anchorComponent = event.entity.components[ARKitAnchorComponent.self] else { return } guard let planeAnchor = anchorComponent.anchor as? PlaneAnchor else { return } let worldSpaceFromExtent = planeAnchor.originFromAnchorTransform * planeAnchor.geometry.extent.anchorFromExtentTransform gameRoot.transform = Transform(matrix: worldSpaceFromExtent) // Add game objects to gameRoot }
-
7:38 - Set up ManipulationComponent
// Set up ManipulationComponent extension Entity { static func loadModelAndSetUp(modelName: String, in bundle: Bundle) async throws -> Entity { let entity = // Load model and assign PhysicsBodyComponent let shapes = // Generate convex shape that fits the entity model // Initialize manipulation ManipulationComponent.configureEntity(entity, collisionShapes: [shapes]) var manipulationComponent = ManipulationComponent() manipulationComponent.releaseBehavior = .stay entity.components.set(manipulationComponent) // Continue entity set up } }
-
9:28 - Subscribe to willBegin ManipulationEvent
// Subscribe to ManipulationEvents // Update the PhysicsBodyComponent to support movement willBegin = content.subscribe(to: ManipulationEvents.WillBegin.self) { event in if var physicsBody = event.entity.components[PhysicsBodyComponent.self] { physicsBody.mode = .kinematic event.entity.components.set(physicsBody) } }
-
9:29 - Subscribe to willEnd ManipulationEvent
// Subscribe to ManipulationEvents // Update the PhysicsBodyComponent to be a dynamic object willEnd = content.subscribe(to: ManipulationEvents.WillEnd.self) { event in if var physicsBody = event.entity.components[PhysicsBodyComponent.self] { physicsBody.mode = .dynamic event.entity.components.set(physicsBody) } }
-
// Set up Scene understanding mesh collision/physics let configuration = SpatialTrackingSession.Configuration( tracking: [.plane], sceneUnderstanding: [.collision, .physics] )
-
11:56 - Set up EnvironmentBlendingComponent
// Set up EnvironmentBlendingComponent entity.components.set( EnvironmentBlendingComponent(preferredBlendingMode: .occluded(by: .surroundings)) )
-
14:20 - Set up MeshInstancesComponent
// Set up MeshInstancesComponent entity let entity = try await ModelEntity(named:"PebbleStriped.usdz") var meshInstancesComponent = MeshInstancesComponent() let instances = try LowLevelInstanceData(instanceCount: 20) meshInstancesComponent[partIndex: 0] = instances instances.withMutableTransforms { transforms in for i in 0..<20 { let scale: Float = .random(in:0.018...0.025) let angle: Float = .random(in:0..<2) * .pi let position = randomPoint(in: inArea, with: scene) let transform = Transform(scale: .init(repeating: scale), rotation: .init(angle: angle,axis: [0, 1, 0]), translation: position) transforms[i] = transform.matrix } } entity.components.set(meshInstancesComponent)
-
17:36 - Load and display a 2D photo
// Load and display a 2D photo guard let url = Bundle.main.url(forResource: "my2DPhoto", withExtension: "heic") else {a return } let component = try await ImagePresentationComponent(contentsOf: url) let entity = Entity() entity.components.set(component)
-
17:57 - Load and display a spatial photo with windowed presentation
// Load and display a spatial photo with windowed presentation guard let url = Bundle.main.url(forResource: "mySpatialPhoto", withExtension: "heic") else { return } var component = try await ImagePresentationComponent(contentsOf: url) // Discover if the component supports windowed spatial photo presentation. if component.availableViewingModes.contains(.spatialStereo) { component.desiredViewingMode = .spatialStereo } entity.components.set(component)
-
18:22 - Load and display a spatial photo with immserive presentation
// Load and display a spatial photo with immersive presentation guard let url = Bundle.main.url(forResource: "mySpatialPhoto", withExtension: "heic") else { return } var component = try await ImagePresentationComponent(contentsOf: url) // Discover if the component supports immersive spatial photo presentation. if component.availableViewingModes.contains(.spatialStereoImmersive) { component.desiredViewingMode = .spatialStereoImmersive } entity.components.set(component)
-
18:56 - Load a spatial photo and use it to generate and present a spatial scene
// Load a spatial photo and use it to generate and present a spatial scene guard let url = Bundle.main.url(forResource: "mySpatialPhoto", withExtension: "heic") else { return } let spatial3DImage = try await ImagePresentationComponent.Spatial3DImage(contentsOf: url) var component = ImagePresentationComponent(spatial3DImage: spatial3DImage) try await spatial3DImage.generate() // Discover if the component supports windowed spatial scene presentation. if component.availableViewingModes.contains(.spatial3D) { component.desiredViewingMode = .spatial3D } entity.components.set(component)
-
20:06 - Generating a spatial scene as needed
// Load a spatial photo and use it to generate and present a spatial scene guard let url = Bundle.main.url(forResource: "mySpatialPhoto", withExtension: "heic") else { return } let spatial3DImage = try await ImagePresentationComponent.Spatial3DImage(contentsOf: url) var component = ImagePresentationComponent(spatial3DImage: spatial3DImage) component.desiredViewingMode = .spatial3D // (or .spatial3DImmersive) entity.components.set(component) try await spatial3DImage.generate()
-
23:35 - Load entity from Data object
// Load entity from Data object if let (data, response) = try? await URLSession.shared.data(from: url) { if let entity = try? await Entity(from: data) { content.add(entity) } }
-
-
- 0:00 - 서론
2019년에 도입된 RealityKit 프레임워크를 사용하면 개발자가 visionOS, iOS, iPadOS, macOS 그리고 이제 tvOS를 포함한 다양한 Apple 플랫폼에서 몰입형 3D 앱 및 게임을 만들 수 있습니다. 피드백을 바탕으로 한 최신 업데이트에서는 ARKit 데이터에 직접 액세스하는 기능, 3D 엔티티에 상호작용을 추가하는 ‘ManipulationComponent’, 원활한 현실 세계 오클루전을 위한 ‘EnvironmentBlendingComponent’, 여러 3D 모델을 효율적으로 렌더링하는 ‘MeshInstancesComponent’ 등 여러 가지 새로운 기능이 도입됩니다. 이러한 기능은 플레이어가 사물과 상호작용하여 상자를 여는 공간 퍼즐 게임을 통해 입증되어 RealityKit이 가상과 현실 세계의 경험을 어떻게 융합하는지 보여 줍니다.
- 3:19 - 업데이트 고정하기
이와 같은 새로운 API를 사용하면 RealityKit을 통해 ARKit 데이터에 직접 액세스할 수 있기 때문에 ‘AnchorEntities’의 기능이 향상됩니다. 평면 추적을 활성화한 ‘SpatialTrackingSession’을 생성하면 ‘AnchorEntities’를 설정하여 최소 차원의 테이블과 같은 특정 실제 표면을 필터링할 수 있습니다. 시스템이 일치하는 표면을 감지하면 ‘AnchorStateEvent’를 트리거하여 변환 및 범위와 같은 ARKit 데이터를 제공합니다. 그런 다음 이 데이터를 사용하여 고정된 표면에 엔티티를 정확하게 배치하여 엔티티가 뷰어에 맞춰 중앙에 정렬되도록 할 수 있습니다.
- 6:52 - ManipulationComponent
몰입형 공간에서는 게임 객체가 적합한 표면에 생성됩니다. RealityKit의 ‘ManipulationComponent’를 사용하면 사람들이 이러한 3D 엔티티를 집어 들고, 회전하고, 손을 바꿀 수 있습니다. ‘configureEntity’ 함수를 호출하면 필요한 구성 요소가 자동으로 추가됩니다. 객체가 해제된 후 재설정되는 것을 방지하려면 ‘releaseBehavior’ 속성을 ‘stay’로 설정합니다. ‘PhysicsBodyComponent’를 추가하면 객체가 바닥으로 떨어집니다. ‘ManipulationEvents’ API는 중력을 켜고 끄는 데 사용됩니다. 누군가가 객체를 놓으면(‘WillEnd’ 이벤트) 중력이 켜지고 객체를 집어 올리면(‘WillBegin’ 이벤트) 중력이 꺼지기 때문에 조작하는 동안 제어 기능을 유지하면서 현실적인 상호작용이 가능합니다.
- 10:01 - 장면 이해
visionOS에서 RealityKit의 Scene Understanding API를 사용하면 실제 환경을 게임의 물리 시뮬레이션에 통합할 수 있습니다. ‘SpatialTrackingSession’ API를 활용하여 주변의 메시를 생성할 수 있습니다. 게임 객체가 이러한 실제 세계의 메시와 충돌하려면 세션을 시작하기 전에 ‘SpatialTrackingSession’ 구성에서 충돌 및 물리에 대한 ‘SceneUnderstandingFlags’를 설정해야 합니다. 이번 업데이트를 통해 게임 객체가 테이블이나 바닥에 떨어뜨리는 등 물리적 환경과 사실적으로 상호작용할 수 있습니다.
- 11:18 - EnvironmentBlendingComponent
최신 RealityKit 업데이트를 사용하면 몰입형 공간 앱에서 ‘EnvironmentBlendingComponent’를 사용하여 가상 엔티티를 실제 주변 환경과 가릴 수 있습니다. 이 구성 요소를 추가하고 혼합 모드를 설정하면 엔티티가 정적 현실 객체에 가려진 더욱 원활한 환경을 만들 수 있습니다. 하지만 이러한 엔티티는 항상 장면 속 다른 가상 객체 뒤에 그려지고 사람 또는 반려동물과 같이 동적으로 움직이는 객체로 가려지지 않는다는 사실을 알아둬야 합니다.
- 12:26 - MeshInstancesComponent
최신 RealityKit 업데이트에서는 엔티티 내에서 단일 메시를 여러 번 그릴 수 있도록 하여 렌더링 효율성을 향상시키는 ‘MeshInstancesComponent’도 도입됩니다. 이러한 새로운 구성 요소는 엔티티를 복제할 필요성을 대체하여 메모리와 처리 공간을 크게 줄입니다. ‘MeshInstancesComponent’를 활용하면 각 메시 인스턴스에 대한 변환 목록을 제공하여 지원되는 플랫폼에서 ‘CustomMaterials’를 통해 고유한 모양을 구현할 수 있습니다. 이 메서드는 GPU 데이터 전송을 최적화하여 성능을 향상시킵니다. 넓은 영역에 이 구성 요소를 사용하면 적절히 제거할 수 있도록 더 작은 엔티티로 나눕니다. ‘MeshInstancesComponent’를 무작위 변형으로 초기화하고 채우는 방법과 장식이 있는 플레이 가능 영역을 만드는 방법에 대한 데모가 있습니다. ‘AnchorStateEvent’, ‘ManipulationComponent’, sceneUnderstanding 플래그, ‘EnvironmentBlendingComponent’ 등의 API를 함께 사용하면 대화형 실제 세계 혼합 AR 경험이 지원됩니다.
- 16:28 - 몰입형 미디어
RealityKit은 올해 상당한 업데이트를 통해 몰입형 미디어에 대한 지원이 강화됩니다. 새로운 구성 요소인 ‘ImagePresentationComponent’를 사용하면 세 가지 유형의 이미지를 표시할 수 있습니다. 바로 기존 2D 이미지, 공간 사진, 공간 장면입니다. 공간 장면은 주목할 만한 추가 기능입니다. 2D 사진에서 생성된 3D 이미지로, 동작 시차를 통해 디오라마 같은 효과를 만들어내고 정적인 이미지를 더욱 매력적으로 만듭니다. 공간 장면을 표현하려면 ‘Spatial3DImage’ 클래스를 사용하여 2D 이미지나 공간 사진에서 장면을 생성한 다음 원하는 뷰 모드를 설정합니다. ‘VideoPlayerComponent’도 공간 비디오, 180도 및 360도 비디오와 같은 Apple Projected Media Profile 비디오, Apple Immersive Video를 포함한 다양한 몰입형 비디오 형식을 지원하도록 업데이트되었습니다. 이러한 비디오를 다양한 뷰 모드로 재생할 수 있으며 Apple Projected Media Profile 비디오에 대한 편의성 설정을 구성할 수 있습니다.
- 21:43 - 액세서리 및 기타 정보
올해 RealityKit 업데이트는 3D 앱 개발을 크게 향상시킵니다. 주요 업데이트 내용은 다음과 같습니다. 공간 액세서리: RealityKit은 이제 햅틱을 사용하여 6자유도로 공간 액세서리를 추적할 수 있도록 지원하여 공유 공간과 전체 공간에서 더욱 몰입감 넘치는 상호작용이 가능합니다. SwiftUI 통합: ‘ViewAttachmentComponent’, ‘PresentationComponent’, ‘GestureComponent’와 같은 새로운 구성 요소를 사용하면 엔티티에 SwiftUI 뷰, 모달 프레젠테이션, 제스처를 추가하는 작업이 간소화됩니다. 엔티티 업데이트: 새로운 엔티티 연결 메서드는 애니메이션 뼈대에 메시를 연결하는 과정을 간소화하고 초기화 프로그램을 사용하면 메모리 내 데이터 객체에서 엔티티를 로드하여 온라인 장면과 USD 스트리밍을 지원합니다. 텍스처 및 호버 효과 지원: RealityKit은 이제 품질을 저해하지 않고도 더 작은 파일 크기에 대한 AVIF 인코딩된 텍스처를 지원합니다. ‘HoverEffectComponent’가 ‘GroupID’로 업데이트되어 호버 효과 활성화에 대한 제어 기능이 더욱 강화되었습니다. 후처리 효과: ‘RealityViews’는 이제 후처리 효과를 지원하여 Metal Performance Shaders, ‘CIFilter’ 또는 iOS, iPadOS, macOS, tvOS 전반의 사용자 정의 셰이더를 사용하여 블룸과 같은 사용자 정의 효과를 추가할 수 있습니다.