Q&A: visionOS용 앱 빌드하기

지난 몇 달 동안 Apple 전문가들은 전 세계 Apple Vision Pro 개발자 랩에서 visionOS에 관한 많은 질문을 받았습니다. 개발자들이 가장 자주 묻는 질문과 이에 대한 답변을 확인해 보고 엔티티, 몰입형 공간, 충돌 모양 등 다양한 새로운 개념에 관한 인사이트를 학습해 보세요.

제스처를 사용하여 엔티티와 어떻게 상호작용할 수 있나요?

제스처 기반 엔티티 상호작용을 활성화하려면 세 가지 핵심 조건을 충족해야 합니다.

  1. 엔티티에 InputTargetComponent(영문)가 있어야 합니다. 그렇지 않으면 엔티티가 제스처 입력을 수신할 수 없습니다.
  2. 엔티티에 CollisionComponent(영문)가 있어야 합니다. 충돌 구성요소의 모양(영문)은 제스처가 실제로 적용되는 영역을 정의합니다. 그러므로 충돌 모양을 엔티티 상호작용에 맞게 지정하세요.
  3. 사용하는 제스처는 반드시 상호작용하려는 엔티티(또는 기타 엔티티)에 타겟팅해야 합니다. 예를 들면 다음과 같습니다.
private var tapGesture: some Gesture {
    TapGesture()
        .targetedToAnyEntity()
        .onEnded { gestureValue in
            
            let tappedEntity = gestureValue.entity
                
            print(tappedEntity.name)
        }
}

사용자가 대화형 엔티티를 바라볼 때 시스템이 기본 강조 효과를 트리거할 수 있도록 해당 엔티티에 HoverEffectComponent(영문)를 제공하는 것도 좋습니다.

윈도우 그룹과 몰입형 공간은 어떤 상황에서 사용하나요?

앱의 기능마다 어떤 장면(Scene) 유형을 적용할지 결정할 때 윈도우(Window), 볼륨(Volume), 몰입형 공간(Immersive Space)의 기술적인 차이를 고려하세요.

결정 시 고려해야 할 주요 기술적 차이점은 다음과 같습니다.

  1. 몰입형 공간이 열리면 사용자가 열어두었던 다른 앱의 윈도우와 볼륨이 숨겨집니다.
  2. 윈도우와 볼륨에서 경계를 넘어가는 콘텐츠는 잘립니다.
  3. 사용자는 윈도우와 볼륨의 배치를 완전히 제어합니다. 몰입형 공간에서는 앱이 콘텐츠의 배치를 완전히 제어합니다.
  4. 볼륨의 크기는 고정되어 있으며, 윈도우는 크기를 조정할 수 있습니다.
  5. ARKit은 앱에 활성화된 몰입형 공간이 있는 경우에만 해당 앱에 데이터를 전달합니다.

Hello World 샘플 코드(영문)를 자세히 알아보고 visionOS 내 각 장면 유형의 동작을 학습하세요.

장면에서 충돌 모양을 어떻게 시각화할 수 있나요?

Debug Visualizations(디버그 시각화) 메뉴에서 Collision Shapes(충돌 모양) 디버그 시각화를 사용하세요. 여러 다양한 디버그 시각화 기능도 이 메뉴에서 찾을 수 있습니다. 디버그 시각화에 대한 자세한 내용은 실행 중인 앱에서 디자인 문제 진단하기(영문)에서 확인하세요.

몰입형 공간에 SwiftUI 뷰를 배치할 수 있나요?

네. offset(x:y:)(영문)offset(z:)(영문) 메서드를 사용하여 몰입형 공간에 SwiftUI 뷰를 배치할 수 있습니다. 이러한 오프셋은 미터(meter)가 아닌 포인트(point) 값을 지정해야 합니다. PhysicalMetric(영문)을 활용하여 미터를 포인트로 변환할 수 있습니다.

실제 뷰의 엔티티를 기준으로 SwiftUI 뷰를 배치하려면 어떻게 해야 하나요?

RealityView Attachment API를 사용하여 SwiftUI 뷰를 생성하고 ViewAttachmentEntity로 사용할 수 있도록 설정하세요. 이 엔티티는 다른 엔티티와 마찬가지로 위치, 방향, 크기를 조정할 수 있습니다.

RealityView { content, attachments in
            
    // Fetch the attachment entity using the unique identifier.
    let attachmentEntity = attachments.entity(for: "uniqueID")!
            
    // Add the attachment entity as RealityView content.
    content.add(attachmentEntity)
            
} attachments: {
    // Declare a view that attaches to an entity.
    Attachment(id: "uniqueID") {
        Text("My Attachment")
    }
}

프로그래밍 방식으로 윈도우를 배치할 수 있나요?

윈도우를 배치하는 API는 없지만, 사용 사례를 Apple에 알려주시면 큰 도움이 될 것 같습니다. 개선 사항 요청을 제출해 주세요. 이 주제와 관련된 자세한 내용은 윈도우의 위치와 크기 지정하기(영문)에서 확인하실 수 있습니다.

사용자가 무엇을 보고 있는지 알 수 있는 방법이 있나요?

개인정보 보호 및 사용자 환경설정에 대한 모범 사례 적용하기(영문)에 명시된 바와 같이 시스템은 카메라 및 센서를 통해 입력되는 정보를 앱에 직접 전달하지 않고 처리합니다. 눈의 움직임이나 시선 방향 정보를 정확하게 얻을 수 있는 방법은 없습니다. 대신 사용자가 상호작용할 수 있는 인터페이스 요소를 만들어서 시스템이 그러한 상호작용을 관리하도록 하세요. 눈의 움직임 정보를 직접적으로 추적하지 않으면서 이 방법으로 해결할 수 없는 사용 사례가 있다면 개선 사항 요청을 제출해 주세요.

visionOS에서 onHover 및 onContinuousHover 동작을 어떻게 호출하나요?

onHover(영문)onContinuousHover(영문) 동작은 사용자가 손가락 또는 연결된 트랙패드의 포인터를 뷰에 올릴 때 호출됩니다.

앱에 자체 제작한 몰입형 환경 텍스처를 표시할 수 있나요?

앱에 ImmersiveSpace(영문)가 활성화되어 있는 경우 UnlitMaterial(영문)로 대형 구(Sphere)를 생성하고 내부를 바라보는 구조로 확장할 수 있습니다.

struct ImmersiveView: View {
    var body: some View {
        RealityView { content in
            do {
                // Create the sphere mesh.
                let mesh = MeshResource.generateSphere(radius: 10)
                
                // Create an UnlitMaterial.
                var material = UnlitMaterial(applyPostProcessToneMap: false)
                
                // Give the UnlitMaterial your equirectangular color texture.
                let textureResource = try await TextureResource(named: "example")
                material.color = .init(tint: .white, texture: .init(textureResource))
                
                // Create the model.
                let entity = ModelEntity(mesh: mesh, materials: [material])
                // Scale the model so that it's mesh faces inward.
                entity.scale.x *= -1
                
                content.add(entity)
            } catch {
                // Handle the error.
            }
        }
    }
}

기존의 스테레오 비디오를 어떻게 MV-HEVC로 변환할 수 있나요?

AVFoundation(영문)에 비디오를 MV-HEVC 형식으로 작성하는 API가 있습니다.

비디오를 MV-HEVC로 변환하는 방법은 다음과 같습니다.

  • 왼쪽 및 오른쪽 뷰에 각각 AVAsset(영문)을 생성합니다.

  • AVOutputSettingsAssistant(영문)를 사용하여 MV-HEVC에 적합한 출력 설정을 확인합니다.

  • 수평 시차(Horizontal Disparity) 조정 및 시야를 지정합니다(애셋별로 다름). 다음의 예시를 참고하세요.

var compressionProperties = outputSettings[AVVideoCompressionPropertiesKey] as! [String: Any]
        
        // Specifies the parallax plane.
        compressionProperties[kVTCompressionPropertyKey_HorizontalDisparityAdjustment as String] = horizontalDisparityAdjustment
        
        // Specifies the horizontal FOV (90 degrees is chosen in this case.)
        compressionProperties[kCMFormatDescriptionExtension_HorizontalFieldOfView as String] = horizontalFOV
// Create a tagged buffer for each stereoView.
                        let taggedBuffers: [CMTaggedBuffer] = [
                            .init(tags: [.videoLayerID(0), .stereoView(.leftEye)], pixelBuffer: leftSample.imageBuffer!),
                            .init(tags: [.videoLayerID(1), .stereoView(.rightEye)], pixelBuffer: rightSample.imageBuffer!)
                        ]
                        
                        // Append the tagged buffers to the asset writer input adaptor.
                        let didAppend = adaptor.appendTaggedBuffers(taggedBuffers,
                                                    withPresentationTime: leftSample.presentationTimeStamp)

visionOS에서 RealityKit 장면에 어떻게 조명을 추가할 수 있나요?

다음의 방법으로 visionOS에서 RealityKit 장면에 조명을 추가할 수 있습니다.

  • 실제 주변 환경에 따라 업데이트되는 자동 시스템 조명 환경을 사용합니다.

  • ImageBasedLightComponent로 자체 이미지에 기반한 조명을 추가합니다. 예시를 보려면 새 visionOS 앱을 만들고 Immersive Space Renderer(몰입형 공간 렌더러)에서 RealityKit을 선택하고 Immersive Space(몰입형 공간)에서 Full(전체)을 선택하세요.

CustomMaterial이 visionOS에서 지원되지 않는다고 들었습니다. 맞춤형 셰이딩을 사용하여 머티리얼을 표현할 수 있는 방법이 있나요?

Reality Composer Pro의 Shader Graph로 맞춤형 셰이딩을 사용하여 새로운 머티리얼을 표현할 수 있습니다. 이렇게 만들어진 머티리얼은 앱에서 ShaderGraphMaterial(영문)로 접근할 수 있습니다. 따라서 셰이더에 입력되는 내용을 코드에서 동적으로 변경할 수 있습니다.

Shader Graph에 관한 자세한 내용은 Reality Composer Pro가 제공하는 머티리얼 살펴보기(한국어 자막)에서 확인하세요.

기기의 위치를 기준으로 엔티티를 배치하려면 어떻게 해야 하나요?

ImmersiveSpace에서 queryDeviceAnchor(atTimestamp:)(영문) 메서드를 사용하여 디바이스를 배치할 수 있습니다.

visionOS용 앱 개발에 대해 자세히 알아보기

Q&A: visionOS를 위한 공간 디자인

View now

Spotlight on: Developing for visionOS

View now

Spotlight on: Developer tools for visionOS

View now

해당 페이지에 포함된 샘플 코드는 Apple Sample Code License(영문)에 따라 제공되었습니다.