在 Unity 的地理空間建立者中,透過程式輔助方式建立及編輯錨定標記

本指南將說明如何使用地理空間建立者編寫 C# 指令碼,以便快速完成常見工作,例如在 Unity 的編輯模式中建立及移動 ARGeospatialCreatorAnchor 物件。如要從預先定義的清單 (例如試算表或 KML 檔案) 建立多個錨點,這項功能就非常實用。

透過 Unity 的地理空間建立者,您可以在 Unity 編輯器中預覽地理空間內容。我們的快速入門指南介紹地理空間創作者,並逐步說明如何以最基本的程式設計,使用 Unity 編輯器 UI 建構首個啟用地理空間功能的 AR 體驗。如果是更進階的專案,您可能想要透過程式輔助方式建立和操控地理空間創作者 GameObjects,而非使用 Unity 編輯器 UI。

本指南假設您已熟悉快速入門導覽課程創作者中介紹的基本地理空間創作者概念,並準備好開始在場景中加入地理空間創作者錨點。您必須啟用地理空間建立者,並使用 API 金鑰和場景中的初始 AR 工作階段物件。如果從頭開始,請先按照快速入門指南的說明操作,並包括「啟用地理空間建立者」一節,再繼續操作。

開始使用

這個範例假設您有一組已知地點:位於美國加州舊金山市,而您想要在該處放置 AR 內容。您必須為每個位置建立錨定物件,然後將基本幾何圖形附加至這些錨點。

建立錨點之前,應先指定 ARGeospatialCreatorOrigin,這是將緯度、經度和海拔高度轉換為 Unity 世界座標的參考點。來源也會包含 CesiumGeoreference 子元件和 Cesium3DTileset 子物件,這可讓 Cesium 在 Unity 編輯器的場景檢視畫面中算繪周圍的區域。為此,您需要 Google Map Tiles API 金鑰 (如快速入門導覽課程所述)

建立來源

地理空間建立者 API 包含可在場景中建立 ARGeospatialCreatorOrigin 的工廠方法,並新增必要的 Cesium 元件。下方程式碼會根據附近的經緯度和高度建立起點,並使用指定的 Map Tiles API 金鑰建立起點:

ARGeospatialCreatorOrigin origin =
  GeospatialCreatorCesiumAdapter.CreateOriginWithCesiumGeoreference(
    37.77954, -122.417581, 0.0, "<MAP_TILES_KEY>");

根據預設,這個物件會放在 (0、0、0) 的 Unity 世界座標中,因此在此範例中可以很順利。

取得 ARAnchorManager 參考資料

您需要 ARAnchorManager 才能在執行階段解析地理空間錨點,因此您也必須在場景中參照 ARAnchorManager。如果您已開始使用隨附 ARCore Extensions 的地理空間範例應用程式,則 Anchor Manager 會連結至「AR Session Origin」 GameObject。假設情境中只有一個錨點管理員,您可以取得如下所示的參照:

ARAnchorManager anchorManager =
    Resources.FindObjectsOfTypeAll<ARAnchorManager>()[0];

現在您已擁有來源和錨定管理員,可以開始建立 ARGeospatialCreatorAnchor 物件。

建立地形錨點

請參考下列 double 值的二維陣列,也就是在美國舊金山市政廳東側三點所代表的精確經緯度:

double[,] _cityHallEastPoints = {
    { 37.77936, -122.418617 }, // in front of city hall
    { 37.77965, -122.418680 }, // right of city hall
    { 37.77917, -122.418577 }}; // left of city hall

假設您想在 AR 應用程式中,為每個地點的一樓放置一個公尺的立方體。以下程式碼會建立 ARGeospatialCreatorAnchor 物件,並將其屬性指派給適當的值:

for (int i = 0; i < _cityHallEastPoints.GetLength(0); i++)
{
  ARGeospatialCreatorAnchor anchor =
    new GameObject("City Hall " + i).AddComponent<ARGeospatialCreatorAnchor>();
  anchor.Origin = origin;
  anchor.AnchorManager = anchorManager;
  anchor.Latitude = _cityHallEastPoints[i, 0];
  anchor.Longitude = _cityHallEastPoints[i, 1];
  anchor.AltitudeType = AnchorAltitudeType.Terrain;

  GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
  cube.transform.parent = anchor.transform;
}

這會在每個點建立地形錨定標記。地理空間建立者會計算相對於 ARGeospatialCreatorOrigin 物件的位置,自動將錨點放在適當的 Unity 世界座標。如要調整地形錨點的海拔高度,請將 Altitude 屬性 (以公尺為單位) 置於地形表面上方或下方。

在執行階段,地形錨點會在執行中應用程式的地面解析,並由 Altitude 屬性偏移。不過在編輯器的場景檢視畫面中,算繪時間的預設高度為 0,而非相對於 3D 圖塊幾何圖形。這通常不是您想要查看的位置,因此您可以在編輯器的場景檢視畫面中,將 UseEditorAltitudeOverride 屬性設為 true,並使用 EditorAltitudeOverride 屬性在 WGS84 公尺內指定海拔高度,藉此覆寫錨點的預設海拔高度:

anchor.UseEditorAltitudeOverride = true;
anchor.EditorAltitudeOverride = -13.5; // WGS84 altitude at ground level for City Hall plaza

這兩個屬性在編輯器模式外沒有任何作用,而且不會編譯到執行中的應用程式。

市政廳廣場的地理空間錨點

建立屋頂錨點

針對下一個錨點,假設您想要將錨點放在都市城的頂樓,您可以用相同方式建立錨定標記,不過 AltitudeType 屬性設為 AnchorAltitudeType.Rooftop

ARGeospatialCreatorAnchor cityHallRoofAnchor =
  new GameObject("City Hall Roof").AddComponent<ARGeospatialCreatorAnchor>();
cityHallRoofAnchor.Origin = origin;
cityHallRoofAnchor.AnchorManager = anchorManager;
cityHallRoofAnchor.Latitude = 37.77959;
cityHallRoofAnchor.Longitude = -122.419006;
cityHallRoofAnchor.AltitudeType = AnchorAltitudeType.Rooftop;

GameObject roofCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
roofCube.transform.parent = cityHallRoofAnchor.transform;

與地形錨點類似,您可以在編輯器的場景檢視畫面中,使用 UseEditorAltitudeOverrideEditorAltitudeOverride 屬性微調頂樓錨點的高度。在這個範例中,WGS84 屋頂的海拔約 10.7 公尺。

屋頂上的地理空間錨點

在特定海拔高度建立錨定標記

我們的最終錨點將放在市政廳圓頂頂端。對這個錨點來說,精確的海拔高度很重要,因此請使用 WGS84 錨點明確設定,而非地形或屋頂錨點:

ARGeospatialCreatorAnchor cityHallDomeAnchor =
  new GameObject("City Hall Dome").AddComponent<ARGeospatialCreatorAnchor>();
cityHallDomeAnchor.Origin = origin;
cityHallDomeAnchor.AnchorManager = anchorManager;
cityHallDomeAnchor.Latitude = 37.77928;
cityHallDomeAnchor.Longitude = -122.419241;
cityHallDomeAnchor.AltitudeType = AnchorAltitudeType.WGS84;
cityHallDomeAnchor.Altitude = 73;

GameObject domeCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
domeCube.transform.parent = cityHallDomeAnchor.transform;

由於 WGS84 已指定高度,因此您不需要使用編輯器專用的高度覆寫。當然,如果編輯器中的地圖圖塊幾何圖形高度與真實世界不符,您仍然可以使用編輯器覆寫功能,在場景檢視畫面中重新調整錨點的位置。

圓頂上的地理空間錨定標記