วิศวกรอาวุโสฝ่ายซอฟต์แวร์
ดูวิธีตรึงและคงประสบการณ์ 3 มิติไว้ในโลกแห่งความเป็นจริงโดยใช้ Unity และ Android XR เซสชันนี้ครอบคลุมเฟรมเวิร์กเอนทิตีเชิงพื้นที่, Cloud Anchor และ Geospatial API ซึ่งแสดงวิธีสร้างแอปที่คำนึงถึงบริบทซึ่งจดจำตำแหน่งทางกายภาพและซิงค์ข้อมูลเชิงพื้นที่ของผู้ใช้หลายคนหนึ่งเครื่องในเซสชันต่างๆ
เราจะตรวจสอบสถาปัตยกรรมเบื้องหลังเอนทิตีเชิงพื้นที่ ทำความเข้าใจวิธีเชื่อมโยงเนื้อหาดิจิทัลกับวัตถุ พื้นผิว และสถานที่ตั้งทางภูมิศาสตร์ที่จับต้องได้ คุณจะได้เรียนรู้เวิร์กโฟลว์ Unity ที่นำไปใช้ได้จริงสำหรับการแมปพื้นที่ การคงเนื้อหาไว้ในเซสชันต่างๆ และการสร้างประสบการณ์ AR/XR ที่รับรู้ตำแหน่งและแชร์ร่วมกันได้
TrySaveAnchorAsync และโหลดซ้ำโดยใช้ GUID ที่เรียงลำดับแล้วข้อความถอดเสียง
โอเค
ขอต้อนรับทุกคน
นี่คือการสร้างสถาปัตยกรรมเนื้อหาเชิงมิติพื้นที่บน Android XR ด้วย Unity
ฉันชื่อ Jennifer Stanton
ฉันทำงานที่ Unity ในตำแหน่งวิศวกรซอฟต์แวร์อาวุโส
ฉันทำงานในทีมฟีเจอร์ XR โดยเฉพาะใน AR Foundation และแพ็กเกจที่เกี่ยวข้องซึ่งนำเทคโนโลยีความจริงเสริมและเทคโนโลยีความจริงแบบผสมมาสู่ Unity
เราชื่อ Levana Chen จากทีม XR เกมเอนจิน ของ Google
ทีมของเรามุ่งเน้นที่การนำเสนอปลั๊กอินและแพ็กเกจที่จะช่วยเพิ่มฟังก์ชันการทำงานของ XR และการผสานรวมเกมเอนจินที่ราบรื่น
ความท้าทายที่ยิ่งใหญ่ที่สุดอย่างหนึ่งที่เราได้ยินจากคุณคือการรองรับแพลตฟอร์ม XR หลายแพลตฟอร์มด้วยฐานของโค้ดเดียวกันนั้นเป็นงานที่หนักหน่วง
AR Foundation เป็นเลเยอร์ API เทคโนโลยีความจริงขยาย (XR) ระดับสูงของ Unity
คุณสามารถกำหนดเป้าหมายแพลตฟอร์ม XR หลายแพลตฟอร์มได้โดยไม่ต้องเขียนโค้ดใหม่ทั้งหมดหรือจัดการฐานของโค้ดหลายรายการ และยังมี API การเขียนสคริปต์เดียวสำหรับฟีเจอร์ AR ในทุกแพลตฟอร์มด้วย
ซึ่งจะช่วยให้คุณมุ่งเน้นไปที่การสร้างแอป เกม หรือประสบการณ์การใช้งานได้ และ Unity จะดูแลรายละเอียดแพลตฟอร์มให้คุณเอง
วิธีหนึ่งที่ AR Foundation ใช้ในการดำเนินการนี้คือผ่านส่วนขยาย OpenXR
ซึ่งเป็นชุด API มาตรฐานอุตสาหกรรมแบบเปิดที่กำหนดโดย Khronos Group
OpenXR ได้สร้างเอนทิตีเชิงพื้นที่ด้วย
ซึ่งเป็นเฟรมเวิร์กสำหรับเนื้อหาดิจิทัลเพื่อนำเสนอและโต้ตอบกับโลกจริง
เอนทิตีเชิงพื้นที่เป็นโมเดลแบบรวมสำหรับการแสดงองค์ประกอบในโลกจริงเป็นออบเจ็กต์ดิจิทัล
เราตื่นเต้นที่จะได้แชร์ข้อมูลล่าสุดเกี่ยวกับ AR Foundation เพื่อให้คุณเริ่มต้นเส้นทางในการสร้างประสบการณ์สำหรับ XR ได้
ต่อไป เราจะพูดถึงความสามารถของ AR Foundation เพื่อให้เนื้อหาดิจิทัลของคุณโต้ตอบกับโลกแห่งความจริงได้
จากนั้นฉันจะอธิบายการตั้งค่าโปรเจ็กต์ ซึ่งรวมถึงแพ็กเกจและทรัพยากร Dependency อื่นๆ เพื่อให้คุณนำไปใช้ในโปรเจ็กต์ได้
จากนั้นเราจะสรุปด้วยการพูดถึงฟีเจอร์บางอย่างที่มีเฉพาะใน Android XR
ดังนั้น วิธีหนึ่งที่ AR Foundation แสดงโลกจริงในรูปแบบดิจิทัลคือระนาบ
ซึ่งก็คือพื้นผิวเรียบในสภาพแวดล้อมจริง เช่น พื้น ผนัง เพดาน รวมถึงโต๊ะและโซฟา
Mesh คือโครงสร้าง 3 มิติที่แสดงเรขาคณิตของโลกจริง
นอกจากนี้ เรายังมีวิธีโต้ตอบกับโลกจริงด้วย Ray Cast
ซึ่งจะกำหนดตำแหน่งที่รังสีตัดกับเนื้อหาดิจิทัล
ให้คิดว่าตัวชี้เป็นเหมือนตัวชี้เลเซอร์ และคุณจะได้รับข้อมูลเกี่ยวกับตำแหน่งที่ตัวชี้เลเซอร์นั้นส่องอยู่
นอกจากนี้ เรายังมี Anchor ซึ่งช่วยให้จุดในพื้นที่คงที่และย้ายตำแหน่งได้
เราจะเจาะลึกเกี่ยวกับ Anchor ภายหลังในการนำเสนอนี้
ดังนั้นทั้ง 4 รายการนี้จึงถือเป็นฟีเจอร์ AR Foundation
นอกจากนี้ยังมีฟีเจอร์อื่นๆ อีกจำนวนหนึ่งที่ไม่ได้กล่าวถึงในสไลด์นี้
โดยเฉพาะอย่างยิ่ง ระนาบและ Anchor จะถือว่าเป็นสิ่งที่ติดตามได้เนื่องจากขยายคลาส ARTrackable และผู้จัดการจะติดตามการอัปเดตจากรันไทม์
มาดูเรื่องเที่ยวบินกันเลย
ระนาบ เรามีคอมโพเนนต์ ARPlane ซึ่งช่วยระบุพื้นผิวเรียบแบบเรียลไทม์
ระนาบเหล่านี้มีป้ายกำกับเชิงความหมายที่คุณสามารถค้นหาได้ เพื่อให้ทราบว่าระนาบนั้นเป็นพื้น โต๊ะ ผนัง และอื่นๆ
ระนาบยังมีขอบเขตแบบไดนามิกด้วย ดังนั้นเมื่อผู้ใช้เคลื่อนที่ผ่านโลกจริงและมองเห็นพื้นผิวมากขึ้น ขอบเขตของระนาบจะขยาย ผสาน และปรับแต่งแบบไดนามิกในแบบเรียลไทม์
นอกจากนี้ เรายังแนบ Mesh Collider เข้ากับเครื่องบินเพื่อจัดการฟิสิกส์ได้ด้วย
คุณดูตัวอย่างการตรวจจับระนาบได้ที่นี่
นี่คือฉาก Raycast ตัวอย่างของ AR Foundation ที่ทำงานบนอุปกรณ์ Android XR
โดยจะตรวจจับรูปหลายเหลี่ยม 2 มิติแบบไดนามิกและเรียลไทม์
คุณสามารถสร้างแอปที่มีฟังก์ชันการทำงานนี้ได้โดยทำตามคู่มือการตั้งค่าโปรเจ็กต์ หรือใช้ตัวอย่างหรือเทมเพลตของเรา
ต่อไปคือ Mesh
Mesh เป็นฟีเจอร์ AR ที่แสดง Mesh 3 มิติของสภาพแวดล้อม
เราสามารถแนบ Mesh Collider เข้ากับ Mesh ที่สร้างขึ้นเหล่านี้ได้ ซึ่งจะช่วยให้เนื้อหาดิจิทัลโต้ตอบกับวัตถุในโลกจริงได้
Mesh ช่วยให้การบดบังวัตถุมีความสมจริง
ดังนั้น วัตถุเสมือนจริงจึงปรากฏอยู่ด้านหลังวัตถุจริงได้
หากวัตถุดิจิทัลเคลื่อนที่ในพื้นที่ได้ คุณสามารถใช้เรขาคณิตเดียวกันเพื่อค้นหาเส้นทางที่หลีกเลี่ยงวัตถุในโลกจริง
ต่อไปคือการแคสต์รังสี
การแคสต์รังสีจะฉายรังสีเสมือนจริงลงในฉาก 3 มิติเพื่อค้นหาจุดตัดโดยที่คุณไม่ต้องกังวลเกี่ยวกับคณิตศาสตร์ที่ซับซ้อน
รังสีที่ฉายจากโปรเจ็กต์ A อาจตัดกับวัตถุ 3 มิติหลายรายการในสภาพแวดล้อมของคุณ
คุณสามารถกำหนดค่าการแคสต์รังสีให้โดนเฉพาะเนื้อหาดิจิทัลบางประเภทได้
เช่น คุณสามารถกำหนดค่าไม่ให้ชนกับระนาบและตัดกับ Mesh เท่านั้น
ตอนนี้เรามาดูแพ็กเกจที่เกี่ยวข้อง
แพ็กเกจเหล่านี้ทั้งหมดจะทำงานร่วมกันเพื่อสื่อสารกันและสร้างประสบการณ์ XR ที่สมบูรณ์
ดังที่กล่าวไว้ AR Foundation จะจัดการฟีเจอร์ต่างๆ เช่น ระนาบและ Anchor
ปลั๊กอิน OpenXR จะจัดการ API แบบเนทีฟในแพลตฟอร์ม XR ต่างๆ ดังนั้นคุณจึงควรใช้แพ็กเกจนี้หากอุปกรณ์ของคุณใช้ OpenXR
คุณสามารถเลือกจับคู่ปลั๊กอิน OpenXR กับแพ็กเกจเอนทิตีเชิงพื้นที่ของ OpenXR เพื่อเข้าถึงส่วนขยายเอนทิตีเชิงพื้นที่โดยเฉพาะได้ และเราจะพูดถึงเรื่องนี้เพิ่มเติมในภายหลัง
หากคุณทราบว่าจะกำหนดเป้าหมายเป็นอุปกรณ์ Android XR โดยเฉพาะ เช่น ชุดหูฟัง XR และแว่นตา XR แบบใช้สาย คุณจะต้องใช้แพ็กเกจ Unity OpenXR Android XR
และเนื่องจากทั้งหมดนี้เป็นไปตามรูปแบบปลั๊กอิน ผลกระทบต่อโค้ดจึงควรมีน้อยที่สุด
บางฟีเจอร์อาจไม่พร้อมใช้งานในแพ็กเกจ AR Foundation บางแพ็กเกจ
ตัวอย่างเช่น หากดูแผนภูมินี้ คุณจะเห็นว่าการสร้างเมชยังไม่พร้อมใช้งานในแพ็กเกจ Unity OpenXR Spatial Entities
การจัดการปลั๊กอิน XR ช่วยให้คุณจัดการฟีเจอร์ OpenXR ที่เลือกในโปรเจ็กต์ได้
ดังนั้นหากคุณอยู่ในเครื่องมือแก้ไข Unity ให้ไปที่ "Edit" (แก้ไข) "Project Settings" (การตั้งค่าโปรเจ็กต์) จากนั้น "XR Plug-in Management" (การจัดการปลั๊กอิน XR) จะอยู่ทางแถบด้านซ้าย
และคุณจะเห็นฟีเจอร์และกลุ่มฟีเจอร์ OpenXR ที่นี่ เพื่อให้คุณเลือกและยกเลิกการเลือกฟีเจอร์และกลุ่มฟีเจอร์ที่ต้องการรวมไว้ในบิลด์ได้
ตัวอย่างเช่น ในภาพหน้าจอนี้ เรากำลังดูส่วนประกอบทั้งหมดที่มาพร้อมกับแพ็กเกจ Android XR OpenXR
จากนั้นคุณสามารถผสมผสานและจับคู่สิ่งเหล่านี้กับเอนทิตีเชิงพื้นที่ได้ เช่น หากต้องการ
นี่คือหน้าต่าง Package Manager
เราได้ไฮไลต์แพ็กเกจบางส่วนที่คุณอาจเห็นในการตั้งค่าโปรเจ็กต์ XR ทั่วไป
อย่างที่เห็น เรามี AR Foundation ซึ่งได้กล่าวถึงไปแล้ว
นอกจากนี้ เรายังมีปลั๊กอิน OpenXR ด้วย
เรามีแพ็กเกจ Android XR
นอกจากนี้ ฉันยังได้ไฮไลต์เครื่องมืออื่นๆ จากแพลตฟอร์มอื่นๆ ด้วย เพราะคุณสามารถสร้างโปรเจ็กต์ที่คอมไพล์ไปยังหลายแพลตฟอร์มได้อย่างแน่นอน
และเรายังมีแพ็กเกจอื่นๆ ที่ด้านขวาล่างด้วย
Composition Layers ซึ่งใช้ได้กับอุปกรณ์ OpenXR, Core Utils ซึ่งมีประโยชน์มากสำหรับทุกอย่างที่เกี่ยวข้องกับ XR, XR Hands และ XR Interaction Toolkit เพื่อรับอินพุต ซึ่งเป็นสิ่งสำคัญมาก
ขั้นตอนถัดไปคือการตรวจสอบความถูกต้องของโปรเจ็กต์
ดังนั้น ขอย้ำอีกครั้งว่านี่เป็นส่วนหนึ่งของ XR Plug-in Management
การตรวจสอบโปรเจ็กต์สามารถตรวจหาฟีเจอร์ที่ซ้ำกัน รวมถึงปัญหาอื่นๆ ในโปรเจ็กต์ที่คุณต้องแก้ไขเพื่อให้โปรเจ็กต์ทำงานได้
แต่ในภาพหน้าจอนี้ ฉันได้ไฮไลต์ฟีเจอร์ที่ซ้ำกันไว้
โดยพื้นฐานแล้ว ข้อความนี้หมายความว่ามีฟีเจอร์เดียวกัน 2 รายการ เช่น เรามี Anchor, อาจมีระนาบและ Raycast อยู่ที่นี่
ผู้ใช้เลือกที่จะรวมฟีเจอร์เหล่านี้ที่ซ้ำกันจากหลายแพ็กเกจ และระบบเพียงแค่แจ้งให้ผู้ใช้เลือกฟีเจอร์ใดฟีเจอร์หนึ่ง
ซึ่งนำเราไปสู่ Anchor ในเครื่องและความคงอยู่ถาวร
Anchor ช่วยให้มั่นใจว่าเนื้อหาดิจิทัลจะยังคงอยู่ในตำแหน่งที่ต้องการในสภาพแวดล้อม ไม่ว่าสถานะการติดตามของเซสชัน AR จะเปลี่ยนแปลงไปอย่างไรก็ตาม
แพลตฟอร์ม AR จะอัปเดตท่าทางของ Anchor โดยอัตโนมัติเมื่อเวลาผ่านไปเพื่อให้แน่ใจว่า Anchor ยังคงอยู่ในตำแหน่งที่สอดคล้องกัน และ Anchor เป็นวิธีที่ดีที่สุดในการตรวจสอบว่าเนื้อหายังคงอยู่ในตำแหน่งเดิมหากคุณเดินออกจาก Anchor แล้วเดินกลับมา
แล้วจะเกิดอะไรขึ้นเมื่อผู้ใช้ปิดแอปและรีสตาร์ทในภายหลัง แล้วกลับมาที่แอปในเซสชันแยกต่างหาก
Anchor แบบถาวรช่วยให้คุณบันทึก Anchor ในเซสชัน AR แล้วโหลดในเซสชันต่อๆ ไปได้
โดยจะยังคงอยู่ตลอดวงจรของแอปและการรีสตาร์ทอุปกรณ์
ภาพที่แสดงที่นี่คือตัวอย่าง Anchor แบบถาวรในโปรเจ็กต์ตัวอย่าง AR Foundation
ฉากตัวอย่างมีเมนูที่มีฟังก์ชันการทำงานทั้งหมดที่รองรับในแพลตฟอร์มนั้น เช่น การบันทึกและการโหลด Anchor
และนั่นก็นำเราไปสู่วงจรของ Anchor แบบถาวร
ก่อนอื่น คุณจะต้องสร้าง Anchor ในเครื่อง ดังนั้นระบบจึงยังไม่ได้บันทึกไว้ที่ใดเลย ไม่ได้บันทึกไว้ในพื้นที่เก็บข้อมูลถาวร เป็นเพียง Anchor ในเครื่องเท่านั้น
จากนั้นคุณจะเก็บข้อมูลไว้ในพื้นที่เก็บข้อมูล
หลังจากนั้น คุณจะรีสตาร์ทแอปได้ แล้วจึงโหลดแอปจากพื้นที่เก็บข้อมูล
บางแพลตฟอร์ม รวมถึง Android XR ยังรองรับการลบหรือยกเลิกการคงอยู่ของ Anchor ด้วย
ผู้ให้บริการเอนทิตีเชิงพื้นที่รองรับการโหลด Anchor ที่บันทึกไว้ทั้งหมดโดยอัตโนมัติ คุณจึงไม่ต้องขอ Anchor แต่ละรายการด้วยตนเองโดยใช้รหัส
ในการตั้งค่าการจัดการปลั๊กอิน XR คุณสามารถเลือกตัวเลือก "โหลด Anchor ที่บันทึกไว้โดยอัตโนมัติ" ในฟีเจอร์เอนทิตีเชิงพื้นที่: Anchor
และการบันทึก Anchor ก็ใช้โค้ดเพียงไม่กี่บรรทัด
ก่อนอื่น เราจะเริ่มในเครื่องมือแก้ไข Unity และตรวจสอบว่าฉากพร้อมแล้วโดยเพิ่มคอมโพเนนต์ AR Anchor Manager ลงในเกมออบเจ็กต์ XR Origin
ผู้จัดการจะอัปเดตฉากด้วย Anchor ที่ติดตามจากรันไทม์
ซึ่งนำเรามาสู่โค้ด
หากต้องการเพิ่ม Anchor คุณเพียงแค่เรียกใช้ TryAddAnchorAsync และส่งท่าทางของตำแหน่งที่ต้องการวาง Anchor
async void CreateAnchorAsync(ARAnchorManager manager, Pose pose) {
var result = await manager.TryAddAnchorAsync(pose);
if (result.status.IsError()) {
// handle error
return;
}
var anchor = result.value;
}ต่อไปคือการนำ Anchor ออก
void RemoveAnchor(ARAnchorManager manager, ARAnchor anchor) {
var result = manager.TryRemoveAnchor(anchor.trackableId);
if (result.status.IsError()) {
// handle error
return;
}
}
void DestroyAnchorComponent(ARAnchor anchor) {
Destroy(anchor);
}และในทำนองเดียวกัน โค้ดก็มีเพียงบรรทัดเดียว
คุณเรียกใช้ TryRemoveAnchor โดยส่งรหัสที่ติดตามได้ของ Anchor
เมื่อสร้าง Anchor ระบบจะกำหนดรหัสที่ติดตามได้ให้แล้ว
และเราก็มี TrySaveAnchorAsync
async void SaveAnchorAsync(ARAnchorManager manager, ARAnchor anchor) {
var result = await manager.TrySaveAnchorAsync(anchor);
if (result.status.IsError()) {
// handle error
return;
}
// Save this value, then return it as an input parameter
SerializableGuid guid = result.value;
}คุณส่ง Anchor ของ AR เป็นอินพุต
ฟังก์ชันนี้จะแสดงผล SerializableGuid ที่ระบุ Anchor ในพื้นที่เก็บข้อมูลถาวร
จากนั้นคุณจะใช้ GUID ได้เมื่อโหลด Anchor
ซึ่งนำเรามาสู่โฆษณา Anchor แบบโหลด
async void LoadAnchorAsync(ARAnchorManager manager, SerializableGuid guid) {
var result = await manager.TryLoadAnchorAsync(guid);
if (result.status.IsError()) {
// handle error
return;
}
ARAnchor anchor = result.value;
}ฟังก์ชันที่จะเรียกใช้ที่นี่คือ TryLoadAnchorAsync และคุณส่ง GUID ที่เรียงลำดับจากก่อนหน้านี้
ซึ่งจะแสดงผลเป็น Anchor ของ AR
เพียงเท่านี้ก็เรียบร้อย
ฟังก์ชันเหล่านี้ช่วยให้คุณจัดการทั้ง Anchor ในเครื่องและ Anchor แบบถาวรได้อย่างง่ายดาย
ดังนั้น การติดตาม Anchor จึงเป็นงานที่ค่อนข้างใช้ทรัพยากรมากในแพลตฟอร์ม AR ส่วนใหญ่
เมื่อทำงานกับ Anchor ให้พิจารณาแนวทางปฏิบัติแนะนำต่อไปนี้ หลีกเลี่ยงการสร้าง Anchor หลายรายการใกล้กันมากเกินไป พิจารณาว่าคุณสามารถใช้ Anchor ใกล้เคียงแทนการสร้าง Anchor อื่นได้หรือไม่ นำ Anchor ออกเมื่อไม่ได้ใช้งานแล้ว และสุดท้าย หากคุณเปิดใช้ฟีเจอร์ AR อื่นเพื่อช่วยคำนวณท่าทางที่ต้องการสำหรับ Anchor ให้พิจารณาว่าคุณสามารถปิดใช้ฟีเจอร์นั้นได้หรือไม่เมื่อสร้าง Anchor สำเร็จแล้ว
และตอนนี้ฉันขอส่งต่อให้ Levana
ขอบคุณ Jennifer
ต่อไป เราจะอธิบายถึงสิ่งที่ Google มีส่วนร่วมในเส้นทาง Android XR ใน Unity
ดังนั้น นอกจากปลั๊กอิน Unity OpenXR ที่ Jennifer ได้แนะนำไปแล้ว Google ยังมี Android XR SDK สำหรับ Unity พร้อมความสามารถเพิ่มเติมที่พร้อมใช้งานในแพลตฟอร์ม Android XR ด้วย
SDK นี้มีฟีเจอร์และแพ็กเกจมากมาย และในการพูดคุยครั้งนี้ เราจะมุ่งเน้นไปที่แพ็กเกจ Android XR Extension สำหรับ Unity
ดังนั้นแพ็กเกจ Android XR Extension สำหรับ Unity จึงเป็นผู้ให้บริการ OpenXR เช่นเดียวกับ Android XR และเอนทิตีเชิงพื้นที่ของ OpenXR
และสถาปัตยกรรมของแพ็กเกจนี้มีลักษณะดังนี้ โดยสามารถทำงานพร้อมกันหรือแยกกันก็ได้
ดังนั้นแพ็กเกจของ Google จึงสร้างขึ้นบนอินเทอร์เฟซ OpenXR OpenXR มาตรฐานโดยตรง เช่นเดียวกับผู้ให้บริการ OpenXR รายอื่นๆ ทั้งหมด
เราจึงแสดงฟีเจอร์ต่างๆ เพื่อเปรียบเทียบกับผู้ให้บริการรายอื่นๆ ทั้งหมด
คุณจึงสามารถใช้ข้อมูลนี้เพื่อช่วยตัดสินใจว่าจะเลือกใช้ตัวเลือกใดเมื่อใดและเพราะเหตุใด
คุณจึงอาจมีคำถามเกี่ยวกับเครื่องหมายเอนทิตีเชิงพื้นที่และสิ่งที่ติดตามได้ที่แสดงในตารางนี้
หมายเหตุ: สำหรับผู้ที่สร้างแอปและประสบการณ์การใช้งานใน Android XR อยู่แล้ว เราได้นำเสนอฟีเจอร์นี้ผ่านส่วนขยายที่ติดตามได้ ซึ่งใช้ได้เฉพาะใน Android XR เท่านั้น
และต่อมาตามที่ Jennifer กล่าวถึง เราได้ทำงานเป็นกลุ่มเปิด OpenXR แล้วเปิดตัวส่วนขยายเอนทิตีเชิงพื้นที่ทางด้านขวา และมอบประสบการณ์การใช้งานที่สอดคล้องกันและข้ามแพลตฟอร์ม
และตอนนี้เรากำลังเลิกใช้งานส่วนขยายที่ติดตามได้เพื่อเปลี่ยนไปใช้เฟรมเวิร์กเอนทิตีเชิงพื้นที่
ซึ่งไม่เพียงแต่จะมีประสิทธิภาพมากกว่าเท่านั้น แต่ยังรองรับการใช้งานข้ามแพลตฟอร์มด้วย
จากนั้นมาดูเอนทิตีเชิงพื้นที่กันอย่างละเอียด
นอกจากที่ Jennifer ได้พูดถึงเครื่องบิน, Ray Casting และ Anchor แล้ว คุณยังจะพบว่าฟีเจอร์นี้ได้รับการรองรับจากผู้ให้บริการเอนทิตีเชิงพื้นที่ เช่น มาร์กเกอร์ ซึ่งสามารถตรวจจับ ถอดรหัสบาร์โค้ด 2 มิติมาตรฐาน และติดตามตำแหน่งในพื้นที่ 3 มิติ รวมถึงรูปภาพที่จะจดจำกราฟิก 2 มิติที่รู้จักและติดตามในพื้นที่ 3 มิติ
จากนั้นก็กรอบล้อมรอบ ซึ่งจะระบุวัตถุจริง เช่น แป้นพิมพ์ แล็ปท็อป หรือเมาส์ และติดตามกรอบล้อมรอบในท่าทาง 3 มิติ
และในตัวอย่างถัดไป เราจะกำหนดค่าฟีเจอร์กรอบล้อมรอบที่แพ็กเกจส่วนขยายของ Google มีให้
มุมมองนี้จะเหมือนกันสำหรับฟีเจอร์ OpenXR ทั้งหมด
ดังนั้น คุณเพียงแค่ต้องเปลี่ยนไปใช้แพลตฟอร์ม Android XR ก่อน จากนั้นเปิดใช้ผู้ให้บริการ OpenXR และเลือกฟีเจอร์ OpenXR ที่ต้องการใช้สร้าง เช่น ฟีเจอร์กรอบล้อมรอบเอนทิตีเชิงพื้นที่ที่แสดงที่นี่ แล้วแก้ไขปัญหาการตรวจสอบโปรเจ็กต์
ซึ่งจะช่วยให้คุณค้นหาทรัพยากร Dependency ทั้งหมดที่ฟีเจอร์หนึ่งๆ ต้องการ จากนั้นจึงแก้ปัญหาความขัดแย้งที่เกิดจากฟีเจอร์หลายรายการที่ส่งผลต่อระบบย่อยเดียวกัน
บางครั้งคุณ ส่วนใหญ่แล้วคุณจะต้องเลือกฟีเจอร์เดียวเท่านั้นหากต้องการใช้ เช่น Anchor, ระนาบ หรือกรอบล้อมรอบที่นี่
และสุดท้าย คุณสามารถสร้างฉากตัวอย่างหรือฉากทดสอบได้
หากต้องการเข้าถึงออบเจ็กต์ที่ติดตามได้ขณะรันไทม์ คุณเพียงแค่เพิ่มคอมโพเนนต์ AR Bounding Box Manager ซึ่งเป็นคอมโพเนนต์ที่คล้ายกับ AR Anchor Manager จากนั้นใช้อินเทอร์เฟซ AR Foundation เพื่อเข้าถึง
หรือจะนำเข้าตัวอย่างเอนทิตีเชิงพื้นที่ที่แพ็กเกจส่วนขยายของเรามีให้เป็นเทมเพลตเพื่อเริ่มต้นใช้งานก็ได้
ความแตกต่างที่สำคัญเมื่อคุณใช้ฟีเจอร์ AR Foundation ใน Android XR มีดังนี้
โดยปกติแล้ว แอปของคุณจำเป็นต้องเข้าถึงข้อมูลที่ละเอียดอ่อนเกี่ยวกับสภาพแวดล้อมเพื่อช่วยให้เข้าใจสภาพแวดล้อมรอบตัวผู้ใช้
และเพื่อปกป้องผู้ใช้ Android XR จะจำกัดระบบ ซึ่งก็คือการเข้าถึงข้อมูลที่อยู่เบื้องหลังสิทธิ์
คุณอาจคุ้นเคยกับเรื่องนี้อยู่แล้ว เช่น การเรียกใช้สิทธิ์ Android ตามปกติ เช่น การเข้าถึงกล้องหรือการเข้าถึงตำแหน่ง เป็นต้น
แนวทางปฏิบัติแนะนำในที่นี้คือปิดใช้คอมโพเนนต์ตัวจัดการเมื่อเริ่มต้นระบบ ไม่ว่าจะจากเครื่องมือแก้ไขตามที่เห็นทางด้านขวา หรือจากสคริปต์ เช่น เหตุการณ์ Awake
void Awake() {
planeManager = GetComponent<ARPlaneManager>();
planeManager.enabled = false;
boundingBoxManager = GetComponent<ARBoundingBoxManager>();
boundingBoxManager.enabled = false;
permissionUtil = GetComponent<AndroidXRPermissionUtil>();
}
void OnEnable() {
StartCoroutine(WaitForPermissions());
}เมื่อให้สิทธิ์ที่จำเป็นทั้งหมดแล้ว คุณจะเปิดใช้ผู้จัดการจากสคริปต์ได้ เช่นเดียวกับที่ตัวช่วย WaitForPermissions ทำที่นี่
IEnumerator WaitForPermissions() {
planeManager.enabled = false;
boundingBoxManager.enabled = false;
yield return new WaitUntil(() =>
permissionUtil.AllPermissionGranted());
// Enable after granted permissions and
// restart subsystems.
planeManager.enabled = true;
boundingBoxManager.enabled = true;
// Save permission status.
permissionGranted = true;
}การทำเช่นนี้จะช่วยหลีกเลี่ยงความล้มเหลวในการเริ่มต้นระบบย่อยที่เกิดจากสิทธิ์ไม่เพียงพอ
และนี่คือฟีเจอร์พิเศษ
ตามที่ Jennifer ได้อธิบายเกี่ยวกับ Anchor โดยใช้ AR Foundation เพื่อขยายความสามารถของ Anchor ใน Android XR แพ็กเกจของเรายังมีฟีเจอร์ใหม่ที่เรียกว่า Anchor ที่แชร์ได้ด้วย
ฟีเจอร์นี้จำลองสิ่งที่ฟีเจอร์ Anchor ของ AR Foundation รองรับในปัจจุบัน และยังมาพร้อมกับฟังก์ชันเพิ่มเติมบางอย่าง เช่น Anchor เชิงพื้นที่ด้วย
และอย่างที่คุณคงนึกภาพออก Anchor คือสะพานเชื่อมที่แท้จริงระหว่างโลกเสมือนจริงกับโลกจริง
และแม้ว่า Jennifer จะอธิบายขั้นตอนการสร้าง การบันทึก และการโหลดให้เราฟังแล้ว แต่ทั้งหมดนี้เกิดขึ้นในพื้นที่จริง เช่น Living Room ของผู้ใช้
แต่ที่อื่นๆ ในโลกล่ะ
และเราจะแชร์ข้อมูลนี้ให้กันและกันได้อย่างไร
และนี่คือจุดที่ Geospatial API เข้ามามีบทบาท
ซึ่งช่วยให้คุณสร้าง Anchor เชิงพื้นที่ตามสถานที่ในโลกจริงได้ เช่น ร้านหนังสือโปรดหรือจุดนัดพบในสวนสาธารณะขนาดใหญ่
ดังนั้น Geospatial API จึงสามารถให้เครื่องมือติดตามตำแหน่งทางภูมิศาสตร์ที่แม่นยำผ่าน VPS หรือที่เรียกว่าระบบกำหนดตำแหน่งเสมือน เช่น GPS แต่ใช้ข้อมูล Street View กลางแจ้งเพื่อให้ผลการติดตามที่แม่นยำยิ่งขึ้น
ดังนั้นบางท่านอาจคุ้นเคยกับมุมมองนี้อยู่แล้วหากเคยมีประสบการณ์ใช้งานฟีเจอร์เชิงพื้นที่ของ ARCore มาก่อน
ดังนั้น หากต้องการเข้าถึง Geospatial API ใน Android XR เราต้องเชื่อมต่อกับแบ็กเอนด์ที่โฮสต์บนแพลตฟอร์ม Google Cloud ก่อน
เนื่องจากแบ็กเอนด์เชิงพื้นที่ทำงานโดยใช้บริการ ARCore ใน Google Cloud คุณจึงทำตามขั้นตอนเดียวกันนี้เพื่อกำหนดค่าโปรเจ็กต์ที่อยู่ในระบบคลาวด์ของ Google ด้วยสิทธิ์เข้าถึง ARCore API ได้
ทั้งหมดนี้จะช่วยให้คุณใช้ฟีเจอร์ Android XR Google Cloud ที่ให้บริการโดยแพ็กเกจส่วนขยายของเราได้
เมื่อเปิดใช้ Geospatial API และรับคีย์ API จากโปรเจ็กต์ Google Cloud แล้ว คุณจะเปิดใช้ฟีเจอร์นี้และกำหนดค่าการตรวจสอบสิทธิ์ผ่านเมนูการตั้งค่า OpenXR ที่แสดงที่นี่ได้ และหรือคุณจะกำหนดค่าด้วยตนเองผ่าน API การเขียนสคริปต์ที่ชื่อว่า TrySetAuthenticationAsync ก็ได้
async Task TrySetAuthentication() {
googleCloudFeature =
OpenXRSettings.Instance
.GetFeature<XRGoogleCloudFeature>();
var result = await googleCloudFeature
.TrySetAuthenticationAsync(
strategy, credential);
if (result.IsSuccess()) {
// Ready to use for geospatial tracker.
} else if (result.IsUnsupported()) {
// Google Cloud feature is not supported
} else if (result.IsKeylessError()) {
// Confirm if keyless has been set up properly.
} else {
// Handling other common OpenXR errors.
}
}โปรดทราบว่าปัจจุบันแพลตฟอร์ม Android XR รองรับเฉพาะการตรวจสอบสิทธิ์ด้วยคีย์ API เท่านั้น แต่จะรองรับข้อมูลเข้าสู่ระบบเพิ่มเติมในอนาคต
ดังนั้น เมื่อตรวจสอบสิทธิ์แล้ว คุณจะใช้เครื่องมือจัดการข้อมูลเชิงพื้นที่เพื่อเข้าถึงความสามารถด้านข้อมูลเชิงพื้นที่ได้
เราขอแนะนำอย่างยิ่งให้ตรวจสอบ Google Maps ก่อนเกี่ยวกับความครอบคลุมของ VPS ก่อนการผสานรวม
ดังนั้น คุณจึงต้องมีสิทธิ์เข้าถึงเครือข่ายเมื่อใช้ฟีเจอร์นี้ด้วย
ดังนั้น XR Geospatial Manager จึงทำงานคล้ายกับคอมโพเนนต์เซสชัน AR ที่ AR Foundation มีให้
ดังนั้นจึงมาพร้อมกับพร็อพเพอร์ตี้สถานะแบบคงที่เพื่อระบุการรองรับระบบและสถานะการติดตามของเครื่องมือติดตามเชิงพื้นที่
คุณสามารถลงทะเบียนเหตุการณ์การเปลี่ยนแปลงสถานะได้โดยใช้ Callback ดังนี้
void OnGeospatialStateChanged(XRGeospatialStateChangedEventArgs eventArgs) {
bool isInitFailed = eventArgs.CurrState == XRGeospatialState.InitializationFailed;
if (isInitFailed && XRGeospatialManager.InitializationResult.IsCloudAuthError()) {
// Handle cloud authentication issues.
} else if (isInitFailed) {
// Check XRGeospatialManager.InitializationResult for other common OpenXR errors.
} else {
// Iterate runtime state change, and handle accordingly.
}
}
private void OnEnable() {
XRGeospatialManager.OnStateChanged += OnGeospatialStateChanged;
}และเมื่อสถานะเชิงพื้นที่ทำงานอยู่ คุณจะใช้อินสแตนซ์ผู้จัดการนี้สำหรับฟังก์ชันการทำงานต่อไปนี้ทั้งหมดได้
ก่อนอื่น เช่น หากต้องการตรวจสอบความพร้อมใช้งานของ VPS ด้วยตำแหน่ง GPS ที่ระบุ เราจะใช้ API สถานที่ของ Unity เพื่อรับค่า GPS แล้วตรวจสอบความพร้อมใช้งานของ VPS
async Task CheckVPSAvailability(CancellationToken token) {
var location = Input.location.lastData;
try {
var result = await geospatialManager.TryCheckVPSAvailabilityAsync(
location.latitude, location.longitude);
token.ThrowIfCancellationRequested();
if (result.status.nativeStatusCode == (int)XrResultAndroid.GeospatialCoordinateInvalid) {
// Invalid coordinates, try with another location.
} else if (result.status.IsError()) {
// Handle common OpenXR error: result.status.ToOpenXRStatus()
} else if (result.value == XRVPSAvailability.Available) {
// You may use this pose to attach geospatial anchors.
var currentGeospatialPose = new XRGeospatialPose(location);
}
}
}ดังนั้น โดยพื้นฐานแล้วนี่คือการแทนที่หากคุณไม่ต้องการตรวจสอบการรองรับ VPS ผ่านแผนที่ แต่คุณต้องออกไปกลางแจ้งเพื่อตรวจสอบสถานะ GPS จริง
จากนั้น คุณยังสามารถแปลงท่าทางระหว่างท่าทาง Unity กับท่าทางเชิงพื้นที่ทางภูมิศาสตร์ได้โดยใช้ TryLocate
// Geospatial Pose -> Unity Pose
var geospatialPose =
new XRGeospatialPose(Input.location.lastData);
if (geospatialManager.TryLocate(
geospatialPose, out XRPoseResult result)) {
if (result.IsPositionValid ||
result.IsPositionTracked) {
transform.position = result.Pose.position;
}
if (result.IsRotationValid ||
result.IsRotationTracked) {
transform.rotation = result.Pose.rotation;
}
}// Unity Pose -> Geospatial Pose
Pose pose = new Pose(
transform.position, transform.rotation);
if (geospatialManager.TryLocate(
pose, out XRGeospatialPoseResult result)) {
if (result.IsPositionValid ||
result.IsRotationValid) {
// You may use for anchor attachment.
}
}และเมื่อนำผลลัพธ์จากการตรวจสอบ VPS หรือการแปลงท่าทางสัมผัส คุณจะสามารถแนบ Anchor เชิงพื้นที่กับท่าทางสัมผัสเชิงภูมิสารสนเทศที่ระบุหรือบนประเภทพื้นผิวที่ทราบ เช่น ภูมิประเทศหรือหลังคา
async void PlaceAnchor(XRGeospatialPose pose) {
try {
Result<ARShareableAnchor> anchorResult;
XRGeospatialSurfaceType typeToPlace = /* Choose your target type */;
if (typeToPlace == XRGeospatialSurfaceType.Default) {
anchorResult = geospatialManager.TryAttachGeospatialAnchor(pose);
} else {
pose.Altitude = 0;
anchorResult = await geospatialManager.TryAttachSurfaceAnchorAsync(typeToPlace, pose);
}
if (anchorResult.status.IsSuccess()) {
// ARShareableAnchorManager will track the anchor and update it.
} else {
// Handle OpenXR failures.
}
}
}และเมื่อนำสิ่งเหล่านี้มารวมกัน คุณจะสร้างประสบการณ์เชิงพื้นที่ที่มหัศจรรย์อย่างแท้จริงได้โดยมีโลกแห่งความเป็นจริงเป็นศูนย์กลาง
ดังนั้น เราจึงวางลูกศรไว้ที่นี่เพื่อนำทางกลุ่มเป้าหมายไปยังสถานที่เป้าหมายในโลกจริง
ตกลง
ดังนั้น Android XR SDK จึงไม่ใช่แพ็กเกจเดียวที่เรามอบให้นักพัฒนาแอป Unity
ตอนนี้ Android XR SDK ของ Google สำหรับ Unity ยังรวมแพ็กเกจ Android XR Interaction Framework และ Android XR Audio ด้วย
และเราตื่นเต้นมากที่จะได้ขยาย Android XR SDK ด้วยการรองรับฟีเจอร์เพิ่มเติม รวมถึงเอนทิตีเชิงพื้นที่มากขึ้นด้วย
เอาล่ะ เรามาถึงช่วงท้ายของเซสชันแล้ว
คุณสามารถติดตามแผนกลยุทธ์ของ Unity ทางออนไลน์เพื่อดูสิ่งที่จะเกิดขึ้นต่อไป
อย่าลืมว่าเรามี Unity 7 ซึ่งเป็น Unity รุ่นถัดไปที่จะเปิดตัวในช่วงต้นปีหน้า
ในระหว่างนี้ คุณสามารถลองใช้เครื่องมือเหล่านี้และสร้างโปรเจ็กต์โดยใช้เทมเพลตเทคโนโลยีความจริงแบบผสม (MR) หรือดูโปรเจ็กต์ตัวอย่าง AR Foundation ใน GitHub ของเรา
นอกจากนี้ หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับเอนทิตีเชิงพื้นที่และการรองรับแพ็กเกจ Unity ของเรา คุณสามารถไปที่หน้าในเว็บไซต์นักพัฒนาแอป Android ได้เลย
และขอขอบคุณทุกคน
เราตื่นเต้นที่จะได้เห็นสิ่งที่คุณสร้างด้วย AR Foundation และเอนทิตีเชิงพื้นที่ใน Android XR
async void CreateAnchorAsync(ARAnchorManager manager, Pose pose) {
var result = await manager.TryAddAnchorAsync(pose);
if (result.status.IsError()) {
// handle error
return;
}
var anchor = result.value;
}void RemoveAnchor(ARAnchorManager manager, ARAnchor anchor) {
var result = manager.TryRemoveAnchor(anchor.trackableId);
if (result.status.IsError()) {
// handle error
return;
}
}
void DestroyAnchorComponent(ARAnchor anchor) {
Destroy(anchor);
}async void SaveAnchorAsync(ARAnchorManager manager, ARAnchor anchor) {
var result = await manager.TrySaveAnchorAsync(anchor);
if (result.status.IsError()) {
// handle error
return;
}
// Save this value, then return it as an input parameter
SerializableGuid guid = result.value;
}async void LoadAnchorAsync(ARAnchorManager manager, SerializableGuid guid) {
var result = await manager.TryLoadAnchorAsync(guid);
if (result.status.IsError()) {
// handle error
return;
}
ARAnchor anchor = result.value;
}void Awake() {
planeManager = GetComponent<ARPlaneManager>();
planeManager.enabled = false;
boundingBoxManager = GetComponent<ARBoundingBoxManager>();
boundingBoxManager.enabled = false;
permissionUtil = GetComponent<AndroidXRPermissionUtil>();
}
void OnEnable() {
StartCoroutine(WaitForPermissions());
}IEnumerator WaitForPermissions() {
planeManager.enabled = false;
boundingBoxManager.enabled = false;
yield return new WaitUntil(() =>
permissionUtil.AllPermissionGranted());
// Enable after granted permissions and
// restart subsystems.
planeManager.enabled = true;
boundingBoxManager.enabled = true;
// Save permission status.
permissionGranted = true;
}async Task TrySetAuthentication() {
googleCloudFeature =
OpenXRSettings.Instance
.GetFeature<XRGoogleCloudFeature>();
var result = await googleCloudFeature
.TrySetAuthenticationAsync(
strategy, credential);
if (result.IsSuccess()) {
// Ready to use for geospatial tracker.
} else if (result.IsUnsupported()) {
// Google Cloud feature is not supported
} else if (result.IsKeylessError()) {
// Confirm if keyless has been set up properly.
} else {
// Handling other common OpenXR errors.
}
}void OnGeospatialStateChanged(XRGeospatialStateChangedEventArgs eventArgs) {
bool isInitFailed = eventArgs.CurrState == XRGeospatialState.InitializationFailed;
if (isInitFailed && XRGeospatialManager.InitializationResult.IsCloudAuthError()) {
// Handle cloud authentication issues.
} else if (isInitFailed) {
// Check XRGeospatialManager.InitializationResult for other common OpenXR errors.
} else {
// Iterate runtime state change, and handle accordingly.
}
}
private void OnEnable() {
XRGeospatialManager.OnStateChanged += OnGeospatialStateChanged;
}async Task CheckVPSAvailability(CancellationToken token) {
var location = Input.location.lastData;
try {
var result = await geospatialManager.TryCheckVPSAvailabilityAsync(
location.latitude, location.longitude);
token.ThrowIfCancellationRequested();
if (result.status.nativeStatusCode == (int)XrResultAndroid.GeospatialCoordinateInvalid) {
// Invalid coordinates, try with another location.
} else if (result.status.IsError()) {
// Handle common OpenXR error: result.status.ToOpenXRStatus()
} else if (result.value == XRVPSAvailability.Available) {
// You may use this pose to attach geospatial anchors.
var currentGeospatialPose = new XRGeospatialPose(location);
}
}
}// Geospatial Pose -> Unity Pose
var geospatialPose =
new XRGeospatialPose(Input.location.lastData);
if (geospatialManager.TryLocate(
geospatialPose, out XRPoseResult result)) {
if (result.IsPositionValid ||
result.IsPositionTracked) {
transform.position = result.Pose.position;
}
if (result.IsRotationValid ||
result.IsRotationTracked) {
transform.rotation = result.Pose.rotation;
}
}// Unity Pose -> Geospatial Pose
Pose pose = new Pose(
transform.position, transform.rotation);
if (geospatialManager.TryLocate(
pose, out XRGeospatialPoseResult result)) {
if (result.IsPositionValid ||
result.IsRotationValid) {
// You may use for anchor attachment.
}
}async void PlaceAnchor(XRGeospatialPose pose) {
try {
Result<ARShareableAnchor> anchorResult;
XRGeospatialSurfaceType typeToPlace = /* Choose your target type */;
if (typeToPlace == XRGeospatialSurfaceType.Default) {
anchorResult = geospatialManager.TryAttachGeospatialAnchor(pose);
} else {
pose.Altitude = 0;
anchorResult = await geospatialManager.TryAttachSurfaceAnchorAsync(typeToPlace, pose);
}
if (anchorResult.status.IsSuccess()) {
// ARShareableAnchorManager will track the anchor and update it.
} else {
// Handle OpenXR failures.
}
}
}