在 Unity 中的 Geospatial Creator 中以编程方式创建和修改锚点

本指南介绍了如何使用 Geospatial Creator 编写 C# 脚本以快速完成常见任务,例如在 Unity 的修改模式下创建和移动 ARGeospatialCreatorAnchor 对象。这对于从预定义列表(如电子表格或 KML 文件)创建多个锚点非常有用。

借助 Unity 中的 Geospatial Creator,您可以在 Unity 编辑器中预览 Geospatial 内容。我们的快速入门指南介绍了 Geospatial Creator,并逐步介绍了如何使用 Unity Editor 界面通过最少量的编程构建支持 Geospatial 的 AR 体验。对于更高级的项目,您可能需要以编程方式创建和操控 Geospatial Creator GameObject,而不是使用 Unity 编辑器界面。

本指南假定您熟悉快速入门中介绍的 Geospatial Creator 基本概念,并且您已经准备好开始向场景添加 Geospatial Creator 锚点。您需要启用 Geospatial Creator,并配置您的 API 密钥以及场景中的初始 AR 会话对象。如果从头开始,请按照快速入门指南操作,并完成启用 Geospatial Creator 部分,然后再继续。

使用入门

在此示例中,假设您在美国加利福尼亚州旧金山市政厅周围有一组已知位置,并且您想在这些位置放置 AR 内容。您需要在这些位置分别创建锚点对象,然后将基本几何图形附加到这些锚点。

在创建锚点之前,您应指定 ARGeospatialCreatorOrigin,这是用于在 Unity 世界坐标之间转换纬度、经度和海拔高度的参考点。该源站还将包含 CesiumGeoreference 子组件和 Cesium3DTileset 子对象,后者允许 Cesium 在 Unity 编辑器的“Scene”视图中渲染周围的区域。为此,您需要一个 Google Map Tiles API 密钥,如快速入门中所述。

创建来源

适用于 Geospatial Creator 的 API 包含一个工厂方法,用于在场景中创建 ARGeospatialCreatorOrigin 并添加所需的 Cesium 组件。以下代码使用指定的 Map Tiles API 密钥在附近的纬度、经度和海拔位置创建出发地:

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

默认情况下,系统会将此对象放置在 Unity 世界坐标中的 (0, 0, 0) 处,这非常适合此示例。

获取 ARAnchorManager 引用

需要 ARAnchorManager 才能在运行时解析地理空间锚点,因此您还需要引用场景中的 ARAnchorManager。如果您从与 ARCore 扩展程序捆绑的 Geospatial 示例应用入手,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;
}

这将在每个点创建地形锚点。Geospatial Creator 会计算锚点相对于 ARGeospatialCreatorOrigin 对象的位置,自动将锚点放置在相应的 Unity 世界坐标上。如需调整地形锚点的海拔高度,请以地形表面以上或以下的米为单位设置 Altitude 属性。

在运行时,地形锚点将在运行中应用的地平面解析,偏移 Altitude 属性。但在编辑器的场景视图中,它们默认以 WGS84 海拔高度 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 指定。当然,如果编辑器中地图图块几何图形的高度与真实世界相比不正确,您仍然可以使用编辑器替换项在场景视图中重新定位锚点。

圆顶上的地理空间锚点