앱에 하위 공간 추가

적용 가능한 XR 기기
이 가이드에서는 이러한 유형의 XR 기기를 위한 환경을 빌드하는 방법을 설명합니다.
XR 헤드셋
유선 XR 안경

하위 공간은 앱 내의 3D 공간 파티션으로, 여기에서 3D 모델을 배치하고 3D 레이아웃을 빌드하고 2D 콘텐츠에 깊이를 더할 수 있습니다. 하위 공간은 공간화가 사용 설정된 경우에만 렌더링됩니다. 홈 공간 또는 비 XR 기기에서는 해당 하위 공간 내의 코드가 무시됩니다.

SpatialPanel, SpatialRow, 및 SpatialColumn과 같은 하위 공간 컴포저블을 사용하여 레이아웃을 만들고 2D 콘텐츠를 3D 공간에 배치할 수 있습니다. 3D 콘텐츠를 배치하려면 3D 모델의 경우 SceneCoreEntity, 스테레오 이미지의 경우 SpatialExternalSurface와 같은 적절한 하위 공간 컴포저블을 사용합니다. Orbiter 또는 SpatialDialog와 같은 일부 XR 구성요소는 2D UI 계층 구조의 어느 곳에서나 사용할 수 있는 표준 2D 컴포저블이지만 SubspaceComposable은 앱의 하위 공간에서 호출해야 합니다. 이렇게 하려면 Subspace 하위 공간 컴포저블을 사용합니다.

하위 공간 계층 구조 정보

최상위 Subspace는 앱에서 호출하는 가장 바깥쪽 하위 공간입니다. Subspace를 호출할 때마다 새로운 독립적인 공간 UI 계층 구조가 생성됩니다. 중첩된 상위 Subspace의 공간 위치, 방향 또는 크기를 상속하지 않습니다.

SpatialPanel 내에 삽입되거나 중첩된 Subspace를 만들려면 Orbiter, SpatialPopup 또는 기타 구성요소, PlanarEmbeddedSubspace를 사용합니다.

PlanarEmbeddedSubspaceSubspace와 두 가지 주요 차이점이 있습니다.

  • 호출된 2D 레이아웃에 참여합니다. 즉, 하위 공간의 높이와 너비는 2D 상위 요소 레이아웃의 높이와 너비에 의해 제한됩니다.
  • 호출된 항목의 하위 요소로 동작합니다. 즉, SpatialPanel 내에 중첩된 하위 공간 컴포저블을 호출하면 해당 하위 공간은 호출된 SpatialPanel 의 하위 요소가 됩니다.

PlanarEmbeddedSubspace의 이러한 동작은 다음과 같은 기능을 지원합니다.

  • 상위 항목과 함께 하위 요소 이동
  • 오프셋 SubspaceModifier를 사용하여 하위 요소의 위치 오프셋
  • 2D UI 위에 떠 있고 2D 레이아웃의 적절한 공간의 높이와 너비에 맞는 3D 객체 표시

하위 공간의 레이아웃 조정

Android XR에서 앱의 레이아웃은 기본적으로 전체 공간 모드의 VolumeConstraintsSubspace에 바인딩됩니다. 따라서 사용자에게 표시되는 공간의 양을 고려하고 그에 따라 레이아웃을 조정해야 합니다. recommendedContentBoxInFullSpace는 콘텐츠가 사용자의 시야 내에 배치될 수 있도록 ActivitySpace 내의 경계 상자에 관한 구체적인 측정기준을 제공합니다.

앱의 기본 콘텐츠는 이 상자 안에 맞아야 합니다. 권장 경계를 초과해야 하는 콘텐츠가 있는 경우 사용자가 머리를 움직여 공간을 탐색하도록 유도하는 레이아웃을 고려하세요. recommendedContentBoxInFullSpace의 기본 제약조건은 맞춤 크기 기반 수정자(예: SubspaceModifier.requiredSizeIn)를 적용하여 재정의할 수 있습니다. 무제한 동작의 경우 allowUnboundedSubspace = true를 설정합니다.

필요에 따라 이러한 구체적인 측정기준을 가져오려면 현재 세션을 사용하여 recommendedContentBoxInFullSpace을(를) 호출합니다. 아래 예시를 참조하세요.

val session = LocalSession.current
session?.scene?.activitySpace?.recommendedContentBoxInFullSpace

앱에 하위 공간 추가

다음 코드 예에서는 앱에 SubspacePlanarEmbeddedSubspace를 추가하는 방법을 보여줍니다.

setContent {
    // This is a top-level subspace
    Subspace {
        SpatialPanel {
            MyComposable()
        }
    }
}

@Composable
private fun MyComposable() {
    Row {
        PrimaryPane()
        SecondaryPane()
    }
}

@Composable
private fun PrimaryPane() {
    // This is an embedded subspace, because PrimaryPane is in a SpatialPanel
    // and that SpatialPanel is in the top-level Subspace
    PlanarEmbeddedSubspace {
        SpatialPanel {}
    }
}

자세한 내용은 SubspacePlanarEmbeddedSubspace에 관한 전체 참고 문서를 확인하세요.