ใช้ Geospatial Anchor เพื่อกำหนดตำแหน่งเนื้อหาในโลกจริงบน Unity

หมุดตำแหน่งทางภูมิศาสตร์เป็นหมุดประเภทหนึ่งที่ให้คุณวางเนื้อหา 3 มิติในโลกแห่งความเป็นจริงได้

ประเภทของหมุดยึดเชิงพื้นที่

หมุดยึดเชิงพื้นที่มี 3 ประเภท ซึ่งแต่ละประเภทจัดการระดับความสูงแตกต่างกันไป ดังนี้

  1. หมุด WGS84:
    หมุด WGS84 ช่วยให้คุณวางเนื้อหา 3 มิติที่ละติจูด ลองจิจูด และระดับความสูงที่ต้องการได้

  2. หมุดเทอร์เรน:
    หมุดเทอร์เรนช่วยให้คุณวางเนื้อหาได้โดยใช้เพียงละติจูดและลองจิจูดที่มีความสูงสัมพันธ์กับภูมิประเทศ ณ ตำแหน่งนั้น ระดับความสูงจะกำหนดตามพื้นดินหรือพื้นตามที่ VPS ทราบ

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

WGS84 ภูมิประเทศ ดาดฟ้า
ตำแหน่งแนวนอน ละติจูด ลองจิจูด ละติจูด ลองจิจูด ละติจูด ลองจิจูด
ตำแหน่งแนวตั้ง สัมพัทธ์กับความสูง WGS84 สัมพันธ์กับระดับพื้นที่ซึ่ง Google Maps เป็นผู้กำหนด สัมพันธ์กับระดับดาดฟ้าที่ Google Maps ระบุ
ต้องแก้ไขจากเซิร์ฟเวอร์ไหม ไม่ ได้ ใช่

ข้อกำหนดเบื้องต้น

โปรดตรวจสอบว่าคุณได้เปิดใช้ Geospatial API แล้วก่อนดำเนินการต่อ

วางหมุดภูมิสารสนเทศ

หมุดแต่ละประเภทมี API เฉพาะสำหรับสร้าง โปรดดูข้อมูลเพิ่มเติมที่ประเภทของหมุดพิกัดภูมิศาสตร์

สร้างจุดยึดจากการทดสอบการคลิก

นอกจากนี้ คุณยังสร้างหมุดตำแหน่งทางภูมิศาสตร์จากผลการทดสอบ Hit Test ได้ด้วย ใช้ท่าทางจาก Hit-Test และแปลงเป็น GeospatialPose ใช้เพื่อวางจุดยึด 1 ใน 3 ประเภทที่อธิบายไว้

รับท่าทางภูมิสารสนเทศจากท่าทาง AR

AREarthManager.Convert(Pose) มีวิธีเพิ่มเติมในการระบุละติจูดและลองจิจูดโดยการแปลงท่าทาง AR เป็นท่าทางภูมิสารสนเทศ

รับท่าทาง AR จากท่าทางภูมิสารสนเทศ

AREarthManager.Convert(GeospatialPose) จะแปลงตำแหน่งแนวนอน ระดับความสูง และการหมุนควอร์เทอร์ไบน์ที่ระบุโดยโลกตามกรอบพิกัดตะวันออก-ขึ้น-ใต้เป็นท่าทาง AR ตามพิกัดโลก GL

เลือกวิธีการที่เหมาะกับกรณีการใช้งานของคุณ

การสร้างหมุดแต่ละวิธีมีข้อดีข้อเสียที่ควรทราบดังนี้

  • เมื่อใช้เรขาคณิตของภาพถนน ให้ใช้ Hit-Test เพื่อแนบเนื้อหากับอาคาร
  • แนะนำให้ใช้จุดยึดบนพื้นดินหรือบนหลังคาแทนจุดยึด WGS84 เนื่องจากใช้ค่าระดับความสูงที่ Google Maps กำหนด

ระบุละติจูดและลองจิจูดของสถานที่

คุณสามารถคํานวณละติจูดและลองจิจูดของสถานที่ได้ 3 วิธีดังนี้

  • ใช้ Geospatial Creator เพื่อดูและเพิ่มประสิทธิภาพโลกด้วยเนื้อหา 3 มิติโดยไม่ต้องไปที่สถานที่จริง ซึ่งช่วยให้คุณวางเนื้อหา 3 มิติที่สมจริงได้โดยใช้ภาพจาก Google Maps ใน Unity Editor ระบบจะคำนวณละติจูด ลองจิจูด การหมุน และระดับความสูงของเนื้อหาให้คุณโดยอัตโนมัติ
  • ใช้ Google Maps
  • ใช้ Google Earth โปรดทราบว่าการหาพิกัดเหล่านี้โดยใช้ Google Earth แทน Google Maps จะมีความคลาดเคลื่อนได้สูงสุดหลายเมตร
  • ไปที่สถานที่ตั้งจริง

ใช้ Google Maps

วิธีรับละติจูดและลองจิจูดของสถานที่โดยใช้ Google Maps

  1. ไปที่ Google Maps ในคอมพิวเตอร์เดสก์ท็อป

  2. ไปที่เลเยอร์ > เพิ่มเติม

  3. เปลี่ยนประเภทแผนที่เป็นดาวเทียม แล้วยกเลิกการเลือกช่องทำเครื่องหมายมุมมองโลกที่มุมซ้ายล่างของหน้าจอ

    ซึ่งจะบังคับใช้มุมมอง 2 มิติและขจัดข้อผิดพลาดที่อาจเกิดขึ้นจากมุมมอง 3 มิติที่เอียง

  4. คลิกขวาที่ตำแหน่งในแผนที่ แล้วเลือกลองจิจูด/ละติจูดเพื่อคัดลอกไปยังคลิปบอร์ด

ใช้ Google Earth

คุณสามารถคํานวณละติจูดและลองจิจูดของสถานที่จาก Google Earth ได้โดยคลิกสถานที่ใน UI และอ่านข้อมูลจากรายละเอียดหมุดพิกัด

วิธีรับละติจูดและลองจิจูดของสถานที่โดยใช้ Google Earth

  1. ไปที่ Google Earth ในคอมพิวเตอร์เดสก์ท็อป

  2. ไปที่เมนูแฮมเบอร์เกอร์ แล้วเลือกรูปแบบแผนที่

  3. สลับสวิตช์สิ่งปลูกสร้าง 3 มิติเป็นปิด

  4. เมื่อปิดสวิตช์อาคาร 3 มิติแล้ว ให้คลิกไอคอนหมุด เพื่อเพิ่มหมุดหมาย ณ ตำแหน่งที่เลือก

  5. ระบุโปรเจ็กต์ที่จะใส่หมุด แล้วคลิกบันทึก

  6. ป้อนชื่อหมุดในช่องชื่อของหมุด

  7. คลิกลูกศรย้อนกลับ ในแผงโปรเจ็กต์ แล้วเลือกเมนู การดำเนินการเพิ่มเติม

  8. เลือกส่งออกเป็นไฟล์ KML จากเมนู

ไฟล์ KLM จะรายงานละติจูด ลองจิจูด และระดับความสูงของจุดสังเกตในแท็ก <coordinates> โดยคั่นด้วยคอมมา ดังนี้

<coordinates>-122.0755182435043,37.41347299422944,7.420342565583832</coordinates>

อย่าใช้ละติจูดและลองจิจูดจากแท็ก <LookAt> ซึ่งระบุตำแหน่งของกล้อง ไม่ใช่ตำแหน่ง

ไปที่สถานที่ตั้งจริง

คุณสามารถคำนวณระดับความสูงของสถานที่ได้โดยไปที่สถานที่นั้นและทำการสังเกตการณ์ในพื้นที่

รับควอร์เทอร์ไบน์การหมุน

GeospatialPose.EunRotation จะดึงข้อมูลการวางแนวจากท่าทางเชิงพื้นที่และแสดงผลควอร์เทอร์ไบน์ที่แสดงถึงเมทริกซ์การหมุนที่เปลี่ยนเวกเตอร์จากเป้าหมายไปยังระบบพิกัดตะวันออก-ขึ้น-เหนือ (EUN) X+ ชี้ไปทางทิศตะวันออก, Y+ ชี้ขึ้นเพื่อหนีจากแรงโน้มถ่วง และ Z+ ชี้ไปทางทิศเหนือ

จุดยึด WGS84

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

ระบบจะรายงานระดับความสูงเป็นเมตรเหนือทรงกลม WGS84 อ้างอิงเพื่อให้ระดับพื้นดินไม่ใช่ 0 แอปของคุณมีหน้าที่รับผิดชอบในการจัดหาพิกัดเหล่านี้สำหรับจุดยึดแต่ละจุดที่สร้าง

วางหมุด WGS84 ในโลกแห่งความเป็นจริง

ระบุระดับความสูงของสถานที่

การกำหนดระดับความสูงของสถานที่เพื่อวางจุดยึดทำได้หลายวิธี ดังนี้

  • หากตำแหน่งของจุดยึดอยู่ใกล้กับผู้ใช้ คุณสามารถใช้ระดับความสูงที่คล้ายกับระดับความสูงของอุปกรณ์ของผู้ใช้
  • เมื่อทราบละติจูดและลองจิจูดแล้ว ให้ใช้ Elevation API เพื่อรับระดับความสูงตามข้อกำหนด EGM96 คุณต้องแปลงระดับความสูง EGM96 ของ Maps API เป็น WGS84 เพื่อเปรียบเทียบกับระดับความสูง GeospatialPose ดู GeoidEval ที่มีทั้งบรรทัดคำสั่งและอินเทอร์เฟซ HTML Maps API จะรายงานละติจูดและลองจิจูดตามข้อกำหนด WGS84 โดยค่าเริ่มต้น
  • คุณดูละติจูด ลองจิจูด และระดับความสูงของสถานที่ได้จาก Google Earth ซึ่งจะทำให้คุณมีข้อผิดพลาดได้สูงสุดหลายเมตร ใช้ละติจูด ลองจิจูด และระดับความสูงจากแท็ก <coordinates> ไม่ใช่แท็ก <LookAt> ในไฟล์ KML
  • หากจุดยึดที่มีอยู่อยู่ใกล้และถ้าคุณไม่ได้อยู่บนแนวเอียง คุณอาจใช้ระดับความสูงจาก GeospatialPose ของกล้อง โดยไม่ต้องใช้แหล่งข้อมูลอื่น เช่น Maps API

สร้าง Anchor

เมื่อคุณมีละติจูด ลองจิจูด ความสูง และควอร์เทอร์ไบน์ของการหมุนแล้ว ให้ใช้ ARAnchorManagerExtensions.AddAnchor() เพื่อกำหนดตำแหน่งเนื้อหาตามพิกัดทางภูมิศาสตร์ที่คุณระบุ

if (earthTrackingState == TrackingState.Tracking)
{
  var anchor =
      AnchorManager.AddAnchor(
          latitude,
          longitude,
          altitude,
          quaternion);
  var anchoredAsset = Instantiate(GeospatialAssetPrefab, anchor.transform);
}

จุดยึดภูมิประเทศ

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

คุณต้องระบุระดับความสูงเหนือภูมิประเทศแทนการป้อนระดับความสูงที่ต้องการ เมื่อค่านี้เป็น 0 หมุดยึดจะอยู่ในระดับเดียวกับภูมิประเทศ

ตั้งค่าโหมดการค้นหาเครื่องบิน

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

โปรดทราบว่าจุดยึดภูมิประเทศจะได้รับผลกระทบจาก Horizontal และ Horizontal | Vertical

ใช้เมนูแบบเลื่อนลงโหมดการตรวจจับเพื่อตั้งค่าโหมดการตรวจจับ

สร้างหมุดเทอร์เรนโดยใช้ Async API ใหม่

หากต้องการสร้างและวางจุดยึดภูมิประเทศ ให้เรียกใช้ ARAnchorManagerExtensions.resolveAnchorOnTerrainAsync()

หมุดจะยังไม่พร้อมใช้งานในทันทีและจำเป็นต้องแก้ไข เมื่อแก้ไขแล้ว รายการดังกล่าวจะพร้อมใช้งานใน ResolveAnchorOnTerrainPromise

public GameObject TerrainAnchorPrefab;

public void Update()
{
    ResolveAnchorOnTerrainPromise terrainPromise =
        AnchorManager.ResolveAnchorOnTerrainAsync(
            latitude, longitude, altitudeAboveTerrain, eunRotation);

    // The anchor will need to be resolved.
    StartCoroutine(CheckTerrainPromise(terrainPromise));
}

private IEnumerator CheckTerrainPromise(ResolveAnchorOnTerrainPromise promise)
{
    yield return promise;

    var result = promise.Result;
    if (result.TerrainAnchorState == TerrainAnchorState.Success &&
        result.Anchor != null)
    {
        // resolving anchor succeeded
        GameObject anchorGO = Instantiate(TerrainAnchorPrefab,
            result.Anchor.gameObject.transform);
        anchorGO.transform.parent = result.Anchor.gameObject.transform;
    }
    else
    {
       // resolving anchor failed
    }

    yield break;
}

ตรวจสอบสถานะของการให้สัญญา

สัญญาจะมี PromiseState ที่เชื่อมโยงอยู่

รัฐ คำอธิบาย
Pending การดำเนินการยังอยู่ระหว่างรอดำเนินการ
Done การดำเนินการเสร็จสมบูรณ์และผลลัพธ์พร้อมใช้งาน
Cancelled การดำเนินการถูกยกเลิกแล้ว

ตรวจสอบสถานะการยึดตามภูมิประเทศของผลลัพธ์ของ Promise

TerrainAnchorState เป็นของการดำเนินการแบบไม่พร้อมกันและเป็นส่วนหนึ่งของผลลัพธ์ Promise สุดท้าย

switch (result.TerrainAnchorState)
{
    case TerrainAnchorState.Success:
        // Anchor has successfully resolved
        break;
    case TerrainAnchorState.ErrorUnsupportedLocation:
        // The requested anchor is in a location that isn't supported by the Geospatial API.
        break;
    case TerrainAnchorState.ErrorNotAuthorized:
        // An error occurred while authorizing your app with the ARCore API. See
        // https://developers.google.com/ar/reference/unity-arf/namespace/Google/XR/ARCoreExtensions#terrainanchorstate_errornotauthorized
        // for troubleshooting steps.
        break;
    case TerrainAnchorState.ErrorInternal:
        // The Terrain anchor could not be resolved due to an internal error.
        break;
    default:
        break;
}

หมุดยึดบนหลังคา

รูปภาพหลักของจุดยึดบนหลังคา

จุดยึดบนหลังคาเป็นจุดยึดประเภทหนึ่งและคล้ายกับจุดยึดบนพื้นด้านบนมาก ความแตกต่างคือคุณจะต้องระบุระดับความสูงเหนือดาดฟ้าแทนระดับความสูงเหนือภูมิประเทศ

สร้างหมุดบนหลังคาโดยใช้ Async API ใหม่

หมุดจะไม่พร้อมใช้งานในทันทีและจำเป็นต้องแก้ไข

หากต้องการสร้างและวางหมุดยึดบนหลังคา ให้โทรหา ARAnchorManagerExtensions.resolveAnchorOnRooftopAsync() คุณจะเข้าถึง PromiseState ของ Promise ได้ด้วย ซึ่งคล้ายกับจุดยึดของภูมิประเทศ จากนั้นตรวจสอบผลลัพธ์ของ Promise เพื่อเข้าถึง RooftopAnchorState

public GameObject RooftopAnchorPrefab;

public void Update()
{
    ResolveAnchorOnRooftopPromise rooftopPromise =
        AnchorManager.ResolveAnchorOnRooftopAsync(
            latitude, longitude, altitudeAboveRooftop, eunRotation);

    // The anchor will need to be resolved.
    StartCoroutine(CheckRooftopPromise(rooftopPromise));
}

private IEnumerator CheckRooftopPromise(ResolveAnchorOnTerrainPromise promise)
{
    yield return promise;

    var result = promise.Result;
    if (result.RooftopAnchorState == RooftopAnchorState.Success &&
        result.Anchor != null)
    {
        // resolving anchor succeeded
        GameObject anchorGO = Instantiate(RooftopAnchorPrefab,
            result.Anchor.gameObject.transform);
        anchorGO.transform.parent = result.Anchor.gameObject.transform;
    }
    else
    {
       // resolving anchor failed
    }

    yield break;
}

ตรวจสอบสถานะของการให้สัญญา

สัญญาจะมี PromiseState ที่เกี่ยวข้อง โปรดดูตารางด้านบน

ตรวจสอบสถานะการระบุตําแหน่งบนหลังคาของผลการค้นหาของ Promise

RooftopAnchorState เป็นของการดำเนินการแบบไม่พร้อมกันและเป็นส่วนหนึ่งของผลลัพธ์ Promise สุดท้าย

switch (result.RooftopAnchorState)
{
    case TerrainAnchorState.Success:
        // Anchor has successfully resolved
        break;
    case RooftopAnchorState.ErrorUnsupportedLocation:
        // The requested anchor is in a location that isn't supported by the Geospatial API.
        break;
    case RooftopAnchorState.ErrorNotAuthorized:
        // An error occurred while authorizing your app with the ARCore API. See
        // https://developers.google.com/ar/reference/unity-arf/namespace/Google/XR/ARCoreExtensions#terrainanchorstate_errornotauthorized
        // for troubleshooting steps.
        break;
    case RooftopAnchorState.ErrorInternal:
        // The Rooftop anchor could not be resolved due to an internal error.
        break;
    default:
        break;
}

ขั้นตอนถัดไป