สร้างด้วยคอนเทนเนอร์เชิงพื้นที่

อุปกรณ์ XR ที่รองรับ
คำแนะนำนี้จะช่วยคุณสร้างประสบการณ์การใช้งานสำหรับอุปกรณ์ XR ประเภทนี้
ชุดหูฟัง XR
แว่นตา XR แบบใช้สาย

Spatial Containers นำการสร้างหน้าต่างเชิงปริมาตรมาสู่ OpenXR คอนเทนเนอร์เชิงพื้นที่ซึ่งกำหนดโดยส่วนขยาย XR_EXT_spatial_container และ XR_EXT_spatial_container_self_rendering ใน OpenXR 1.1 คือพื้นที่ปริมาตร 3 มิติที่ระบบจัดการในพื้นที่ของผู้ใช้ ซึ่งแอปของคุณจะแสดงผลเนื้อหา 3 มิติโดยใช้เลเยอร์องค์ประกอบ OpenXR มาตรฐาน

โดยปกติแล้ว เซสชัน OpenXR จะอ้างสิทธิ์การเข้าถึงขอบเขตการมองเห็นทั้งหมดของผู้ใช้แต่เพียงผู้เดียว คอนเทนเนอร์เชิงพื้นที่ช่วยให้แอปแสดงผลเนื้อหา OpenXR 3 มิติภายในกล่อง 3 มิติที่มีขอบเขตในสภาพแวดล้อมของผู้ใช้ หรือเปลี่ยนไปใช้ประสบการณ์ที่สมจริงแบบเต็มหน้าจอและไม่มีขอบเขตได้ทุกเมื่อ

เกี่ยวกับคอนเทนเนอร์เชิงพื้นที่

คอนเทนเนอร์เชิงมิติพื้นที่คือขอบเขต 3 มิติที่มีขอบเขตหรือไม่มีขอบเขตซึ่งจัดการโดยระบบ Android XR และแสดงผลโดยแอป OpenXR ของคุณ

  • โหมดมีขอบเขต: แอปจะแนะนำขนาด 3 มิติ (ความกว้าง ความสูง และความลึกเป็นเมตร) และระบบจะจัดสรรกรอบล้อมรอบ 3 มิติในสภาพแวดล้อมของผู้ใช้ แอปของคุณแสดงผลเนื้อหา 3 มิติแบบสเตอริโอภายในปริมาตร และระบบจะตัดเนื้อหาที่แสดงผลให้อยู่ภายในขอบเขตของกล่อง 3 มิติ
  • โหมดใหญ่พิเศษ: คอนเทนเนอร์เชิงพื้นที่ขยายออกไปอย่างไม่มีที่สิ้นสุด ทำให้แอปของคุณมีขอบเขตการมองเห็นทั้งหมดของผู้ใช้เหมือนกับเซสชัน OpenXR แบบเต็มหน้าจอแบบดั้งเดิม
คอนเทนเนอร์เชิงพื้นที่ 3 รายการทำงานพร้อมกันในโหมด Full Space ได้แก่ คอนเทนเนอร์ภูมิประเทศ 3 มิติสีส้มที่ล็อกไว้กับพื้น โมเดลเป็ด 3 มิติสีน้ำเงินที่มี UI 2 มิติแนบอยู่ และคอนเทนเนอร์ UI 2 มิติสีเขียว
รูปที่ 1 คอนเทนเนอร์เชิงพื้นที่หลายรายการในโหมด Full Space: ปริมาตรภูมิประเทศ 3 มิติที่ล็อกกับพื้น (ซ้าย) ปริมาตรเป็ด 3 มิติที่จับคู่กับ UI 2 มิติ (กลาง) และคอนเทนเนอร์ UI 2 มิติ (ขวา)

วิธีที่ผู้ใช้โต้ตอบกับคอนเทนเนอร์เชิงพื้นที่

ระบบ Android XR จะจัดการการควบคุมหน้าต่างของคอนเทนเนอร์เชิงพื้นที่และการวางตำแหน่งในพื้นที่จริง ซึ่งจะมอบโมเดลการโต้ตอบที่สอดคล้องกันในแอปต่างๆ ดังนี้

  • การย้ายและการเปลี่ยนตำแหน่ง: ผู้ใช้สามารถจับแฮนเดิลระบบของคอนเทนเนอร์เชิงพื้นที่ได้โดยใช้ท่าทางของมือ (เช่น การบีบ) หรือตัวควบคุมการเคลื่อนไหวเพื่อเปลี่ยนตำแหน่งในพื้นที่ 3 มิติ
  • การย่อและการปิด: ตัวควบคุมหน้าต่างระบบช่วยให้ผู้ใช้ย่อหรือปิดคอนเทนเนอร์เชิงพื้นที่แต่ละรายการได้ เมื่อผู้ใช้ปิดคอนเทนเนอร์ ระบบจะแจ้งเตือนแอปของคุณเพื่อให้ล้างทรัพยากรได้
  • การล็อกกับพื้นด้วยความเข้าใจฉาก: เมื่อแอปประกาศและขอสิทธิ์ android.permission.SCENE_UNDERSTANDING_COARSE ระบบจะเปิดใช้การสแนปพื้นผิวโดยอัตโนมัติเพื่อให้ผู้ใช้วางและล็อกคอนเทนเนอร์เชิงพื้นที่กับพื้นจริงได้โดยไม่ต้องกำหนดค่าแอปเพิ่มเติม ดังที่แสดงโดยคอนเทนเนอร์ภูมิประเทศสีส้มในรูปที่ 1
  • การโต้ตอบ 3 มิติโดยตรง: เมื่อคอนเทนเนอร์ได้รับการโฟกัสและโต้ตอบได้ ผู้ใช้จะโต้ตอบกับเนื้อหา 3 มิติภายในวอลุ่มได้โดยตรงโดยใช้การติดตามการเคลื่อนไหวของมือ การจ้องมอง หรือตัวควบคุม 6DoF
ผู้ใช้โต้ตอบกับเป็ด 3 มิติภายในคอนเทนเนอร์เชิงพื้นที่สีน้ำเงินที่มีขอบเขตโดยใช้การติดตามการเคลื่อนไหวของมือ
รูปที่ 2 ผู้ใช้โต้ตอบกับเนื้อหา 3 มิติภายในคอนเทนเนอร์เชิงพื้นที่ที่มีขอบเขตโดยใช้การติดตามการเคลื่อนไหวของมือ
  • การเปลี่ยนระหว่างโหมดจำกัดและโหมดใหญ่พิเศษ: ผู้ใช้หรือแอปของคุณสามารถสลับคอนเทนเนอร์ระหว่างกล่อง 3 มิติที่จำกัดกับมุมมองใหญ่พิเศษแบบเต็มหน้าจอที่ไม่จำกัดได้โดยไม่ต้องรีสตาร์ทเซสชัน OpenXR
ฉากเป็ด 3 มิติหลังจากเปลี่ยนจากคอนเทนเนอร์เชิงพื้นที่แบบมีขอบเขตเป็นมุมมองสมจริงแบบเต็มหน้าจอที่ไม่มีขอบเขต
รูปที่ 3 คอนเทนเนอร์เชิงพื้นที่หลังจากเปลี่ยนจากโหมดจำกัดเป็นโหมดใหญ่พิเศษ ซึ่งจะเติมเต็มขอบเขตการมองเห็นของผู้ใช้
  • โหมดติดตามขณะเดินทาง: เนื่องจากระบบจะควบคุมท่าทางของพื้นที่พิกัดของคอนเทนเนอร์เชิงพื้นที่แต่ละรายการ (xrCreateSpatialContainerSpaceEXT) ผู้ใช้จึงสามารถเปิดใช้โหมดติดตามจากการควบคุมหน้าต่างของระบบเพื่อให้คอนเทนเนอร์ 3 มิติที่มีขอบเขตติดตามผู้ใช้โดยอัตโนมัติและอยู่ในขอบเขตการมองเห็นขณะที่ผู้ใช้เดินไปมา โดยไม่ต้องกำหนดค่าเพิ่มเติมในแอป

วิธีใช้คอนเทนเนอร์เชิงพื้นที่ใน Android XR

เมื่อสร้างแอปด้วยคอนเทนเนอร์เชิงพื้นที่ ให้ออกแบบฉากตามขอบเขตของคอนเทนเนอร์ การเปลี่ยนแปลงสถานะ และโหมดผสมพื้นหลัง

ปรับเนื้อหา 3 มิติให้พอดีกับขอบเขตของคอนเทนเนอร์

ในโหมดจำกัดขอบเขต จุดเริ่มต้น (0, 0, 0) ของพื้นที่คอนเทนเนอร์เชิงพื้นที่ (xrCreateSpatialContainerSpaceEXT) จะอยู่ที่กึ่งกลางของกรอบล้อมรอบ 3 มิติ เนื่องจากระบบจะจัดการท่าทางของพื้นที่คอนเทนเนอร์ในสภาพแวดล้อมของผู้ใช้ แอปของคุณจึงแสดงผลเนื้อหา 3 มิติที่สัมพันธ์กับ (0, 0, 0) ขณะที่ระบบจะจัดการการเปลี่ยนตำแหน่งของผู้ใช้และโหมดติดตาม ระบบจะตัดเรขาคณิตที่แสดงผลนอกความกว้าง ความสูง หรือความลึกของกล่องเพื่อให้เนื้อหาอยู่ภายในปริมาตรที่กำหนด

แอปควรฟังเหตุการณ์การเปลี่ยนแปลงขอบเขตจากรันไทม์และปรับขนาดหรือเปลี่ยนตำแหน่งฉาก 3 มิติเพื่อให้เนื้อหาหลักพอดีกับขนาดปัจจุบันของคอนเทนเนอร์ เมื่อคอนเทนเนอร์เปลี่ยนเป็นโหมดใหญ่พิเศษ ขอบเขตจะไม่มีที่สิ้นสุดและคุณสามารถคืนค่าฉากเป็นสเกลโลกแบบ 1:1 เต็มรูปแบบได้

ตอบสนองต่อการเปลี่ยนแปลงสถานะคอนเทนเนอร์

แทนที่จะจัดการระดับการมองเห็นและการโฟกัสเฉพาะในระดับแอปพลิเคชัน คอนเทนเนอร์เชิงพื้นที่แต่ละรายการจะรายงานสถานะของตนเองเพื่อให้แอปตอบสนองตามนั้นได้

  • การแสดงผล: ระบุว่าขณะนี้คอนเทนเนอร์แสดงหรือซ่อนอยู่ หยุดภาพเคลื่อนไหว เสียง หรือการอัปเดตการจำลองชั่วคราวขณะที่คอนเทนเนอร์ซ่อนอยู่ นอกจากนี้ แอปยังขอให้แสดงหรือซ่อนคอนเทนเนอร์ได้ด้วย
  • ความสามารถในการโต้ตอบ: ระบุว่าคอนเทนเนอร์ได้รับการโฟกัสและรับอินพุตของผู้ใช้จากการติดตามการเคลื่อนไหวของมือ ตัวควบคุม หรือการจ้องมองหรือไม่ เปิดหรือปิดใช้ไฮไลต์แบบอินเทอร์แอกทีฟและการจัดการอินพุตเมื่อโฟกัสเปลี่ยนไป
  • โหมดขอบเขต: ระบุว่าคอนเทนเนอร์อยู่ในโหมด XR_SPATIAL_CONTAINER_BOUNDS_MODE_BOUNDED_EXT (ถูกตัดเป็นกล่อง 3 มิติ) หรือ XR_SPATIAL_CONTAINER_BOUNDS_MODE_IMMERSIVE_EXT (เต็มหน้าจอแบบไม่มีขอบเขต) อัปเดตสเกลฉากและสลับภาพสภาพแวดล้อม (เช่น สกายบ็อกซ์หรือการส่งผ่าน) เมื่อโหมดเปลี่ยนไป แอปของคุณยังสามารถขอเปลี่ยนระหว่างโหมดขอบเขตและโหมดใหญ่พิเศษได้ทุกเมื่อ

ใช้ความโปร่งใสแบบผสมอัลฟ่าในโหมดที่มีขอบเขต

ในโหมดที่มีขอบเขต พื้นหลังโปร่งใสจะช่วยให้ผู้ใช้มองเห็นสภาพแวดล้อมจริงและหน้าต่างอื่นๆ รอบโมเดล 3 มิติได้ กำหนดค่ากล้องหรือวิวพอร์ตด้วยพื้นหลังโปร่งใสและใช้โหมดผสมสภาพแวดล้อมแบบผสมอัลฟ่า เมื่อเปลี่ยนไปใช้โหมดใหญ่พิเศษ คุณจะเปิดใช้โหมดส่งผ่านภาพต่อไปหรือเปลี่ยนไปใช้สภาพแวดล้อม Skybox แบบทึบแสงก็ได้

ตรวจสอบความพร้อมใช้งานของฟีเจอร์และกำหนดค่าไฟล์ Manifest

คอนเทนเนอร์เชิงมิติพื้นที่ต้องใช้อุปกรณ์ Android XR ที่รองรับ API เชิงมิติพื้นที่ระดับ 4 ขึ้นไป แทนที่จะตรวจสอบระดับ Android API โดยตรง ให้ค้นหารันไทม์ OpenXR เพื่อพิจารณาว่าระบบรองรับคอนเทนเนอร์เชิงพื้นที่หรือไม่โดยเรียกใช้ xrEnumerateInstanceExtensionProperties เพื่อยืนยันว่า XR_EXT_spatial_container และ XR_EXT_spatial_container_self_rendering พร้อมใช้งาน และเรียกใช้ xrGetSystemProperties ด้วย XrSystemSpatialContainerPropertiesEXT เพื่อตรวจสอบ supportsBounded และ supportsImmersive

ก่อนสร้างแอปที่ใช้คอนเทนเนอร์เชิงพื้นที่ ให้กำหนดค่าโหมดเริ่มต้นกิจกรรมและสิทธิ์เฉพาะฟีเจอร์ใน AndroidManifest.xml

เปิดใช้โหมด Full Space ใน AndroidManifest.xml

คอนเทนเนอร์เชิงพื้นที่ต้องใช้โหมด Full Space Managed แม้จะเป็นแอป OpenXR แบบสแตนด์อโลนก็ตาม แอป OpenXR แบบเต็มหน้าจอแบบดั้งเดิมจะประกาศ XR_ACTIVITY_START_MODE_FULL_SPACE_UNMANAGED เพื่อควบคุมการแสดงผลแต่เพียงผู้เดียวโดยไม่มีการจัดการหน้าต่างระบบ ในทางตรงกันข้าม แอปที่ใช้คอนเทนเนอร์เชิงมิติพื้นที่จะอาศัยเครื่องมือจัดวางระบบ Android XR เพื่อจัดการปริมาตรที่ถูกจำกัดขอบเขตแบบ 3 มิติ การควบคุมหน้าต่าง และการจัดวางเชิงมิติพื้นที่ในโหมด Full Space และต้องตั้งค่า android.window.PROPERTY_XR_ACTIVITY_START_MODE เป็น XR_ACTIVITY_START_MODE_FULL_SPACE_MANAGED ดังนี้

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application ...>
        <!-- Spatial Containers require Full Space Managed mode -->
        <property
            android:name="android.window.PROPERTY_XR_ACTIVITY_START_MODE"
            android:value="XR_ACTIVITY_START_MODE_FULL_SPACE_MANAGED" />

        <activity android:name=".MainActivity" ...>
            <!-- Optional hint declaring which bounds modes the activity uses -->
            <property
                android:name="org.khronos.openxr.PROPERTY_ACTIVITY_HINT_XR_SPATIAL_CONTAINER_USED_BOUNDS_MODES"
                android:value="XR_SPATIAL_CONTAINER_BOUNDS_MODE_BOUNDED_EXT|XR_SPATIAL_CONTAINER_BOUNDS_MODE_IMMERSIVE_EXT" />
        </activity>
    </application>
</manifest>

ประกาศและขอสิทธิ์เฉพาะฟีเจอร์

การสร้างและการแสดงผลคอนเทนเนอร์เชิงพื้นที่พื้นฐานไม่จำเป็นต้องใช้สิทธิ์รันไทม์ที่เป็นอันตราย อย่างไรก็ตาม ฟีเจอร์บางอย่างจำเป็นต้องมีการประกาศและขอสิทธิ์ Android XR ที่เกี่ยวข้อง ดังนี้

  • หากต้องการล็อกและยึดคอนเทนเนอร์เชิงพื้นที่กับพื้นจริงโดยใช้การทำความเข้าใจฉาก ให้ประกาศและขอสิทธิ์ android.permission.SCENE_UNDERSTANDING_COARSE ที่เป็นอันตรายที่รันไทม์
  • หากต้องการติดตามท่าทางศีรษะของผู้ใช้ใน OpenXR ให้ประกาศและขอ android.permission.HEAD_TRACKING
<uses-permission android:name="android.permission.HEAD_TRACKING" />
<uses-permission android:name="android.permission.SCENE_UNDERSTANDING_COARSE" />

ดูรายละเอียดเกี่ยวกับการประกาศและการขอสิทธิ์ XR ที่เป็นอันตรายที่รันไทม์ได้ที่ทำความเข้าใจสิทธิ์สำหรับ XR

เปิดใช้คอนเทนเนอร์เชิงพื้นที่ในโปรเจ็กต์

คุณสามารถสร้างด้วยคอนเทนเนอร์เชิงพื้นที่โดยใช้ Unity, Godot หรือใช้ OpenXR ใน C++ โดยตรง เลือกแท็บเพื่อดูข้อกำหนดเบื้องต้น การตั้งค่าเครื่องมือแก้ไข และตัวอย่างโค้ดสำหรับสภาพแวดล้อมที่ต้องการ

Unity

สิ่งที่ต้องมีก่อน

กำหนดค่าโปรเจ็กต์

  1. ไปที่ Edit > การตั้งค่าโปรเจ็กต์ > XR Plug-in Management > OpenXR
  2. คลิกการตั้งค่า ข้าง Android XR (ส่วนขยาย): การจัดการเซสชัน แล้วล้าง XR แบบสมจริง
  3. ในรายการ OpenXR Feature Groups ให้เปิดใช้ Spatial Container

ใช้ XRSpatialContainerFeature ใน C# เพื่อค้นหาขอบเขต ตอบสนองต่อเหตุการณ์คอนเทนเนอร์ และสลับระหว่างโหมดที่มีขอบเขตและโหมดใหญ่พิเศษ

void OnEnable()
{
    XRSpatialContainerFeature.OnSpatialContainerBoundsChanged += OnBoundsChanged;
}

private void OnBoundsChanged(Vector3 bounds, bool infiniteBounds)
{
    float minScale = Mathf.Min(bounds.x, bounds.y, bounds.z);
    transform.localScale = infiniteBounds ? Vector3.one : Vector3.one * minScale;
}

public void SetImmersiveMode(bool immersive)
{
    XRSpatialContainerFeature.TryRequestBoundsMode(immersive);
}

ดูขั้นตอนการตั้งค่าโปรเจ็กต์ การกำหนดค่าไฟล์ Manifest และการจัดการสิทธิ์ทั้งหมดได้ที่หัวข้อใช้คอนเทนเนอร์เชิงพื้นที่ใน Unity

Godot

สิ่งที่ต้องมีก่อน

กำหนดค่าโปรเจ็กต์

  1. ไปที่ Project > การตั้งค่าโปรเจ็กต์ เปิดใช้ Advanced Settings แล้วไปที่ General > XR > OpenXR > Extensions
  2. ในส่วนย่อย Spatial Container ให้เลือกเปิดใช้ แล้วกำหนดค่า Bounds Mode และ Bounds
  3. ไปที่โปรเจ็กต์ > ส่งออก... > Android แล้วเลือกใช้ฟีเจอร์ทดลองในส่วนฟีเจอร์ Android XR

ใช้ซิงเกิลตัน OpenXRSpatialContainerExtension ใน GDScript เพื่อตอบสนองต่อขอบเขตคอนเทนเนอร์และการเปลี่ยนแปลงโหมด

func _ready() -> void:
    if OpenXRSpatialContainerExtension.is_enabled():
        OpenXRSpatialContainerExtension.spatial_container_bounds_changed.connect(
            _on_bounds_changed
        )

func _on_bounds_changed(_rid: RID, bounds: Vector3) -> void:
    scale = Vector3.ONE * min(bounds.x, bounds.y, bounds.z)

func set_immersive_mode() -> void:
    OpenXRSpatialContainerExtension.request_main_spatial_container_bounds_mode(
        OpenXRSpatialContainerState.IMMERSIVE
    )

ดูการตั้งค่าโปรเจ็กต์ สิทธิ์การส่งออก และตัวอย่าง GDScript ทั้งหมดได้ที่หัวข้อใช้คอนเทนเนอร์เชิงพื้นที่ใน Godot

OpenXR

สิ่งที่ต้องมีก่อน

เปิดใช้ XR_EXT_spatial_container และ XR_EXT_spatial_container_self_rendering เมื่อสร้าง XrInstance จากนั้นสร้างและแสดงผลคอนเทนเนอร์เชิงพื้นที่

// 1. Enable the Spatial Container extensions during xrCreateInstance
const char* enabledExtensions[] = {
    XR_EXT_SPATIAL_CONTAINER_EXTENSION_NAME,
    XR_EXT_SPATIAL_CONTAINER_SELF_RENDERING_EXTENSION_NAME,
};

// 2. Configure and create a self-rendering spatial container
XrSpatialContainerConfigurationSelfRenderingEXT selfRenderingConfig{
    .type = XR_TYPE_SPATIAL_CONTAINER_CONFIGURATION_SELF_RENDERING_EXT,
    .next = nullptr,
    .viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO,
    .suggestedBounds = {1.5f, 1.5f, 1.5f}, // Width, height, depth in meters
};

XrSpatialContainerCreateInfoEXT createInfo{
    .type = XR_TYPE_SPATIAL_CONTAINER_CREATE_INFO_EXT,
    .next = &selfRenderingConfig,
    .spatialContainerConfig =
        reinterpret_cast<const XrSpatialContainerConfigurationBaseHeaderEXT*>(
            &selfRenderingConfig),
};

XrSpatialContainerEXT spatialContainer = XR_NULL_HANDLE;
xrCreateSpatialContainerEXT(session, &createInfo, &spatialContainer);

// 3. Request bounded mode and make the container visible
xrRequestSpatialContainerBoundsModeEXT(
    spatialContainer, XR_SPATIAL_CONTAINER_BOUNDS_MODE_BOUNDED_EXT);
xrRequestSpatialContainerVisibilityEXT(spatialContainer, XR_TRUE);

ดูเพิ่มเติม


OpenXR™ และโลโก้ OpenXR เป็นเครื่องหมายการค้าของ The Khronos Group Inc. และจดทะเบียนเป็นเครื่องหมายการค้าในจีน สหภาพยุโรป ญี่ปุ่น และสหราชอาณาจักร