使用 Unity 的 AR Foundation 创建 AR 游戏

1. 概览

ARCore 是 Google 推出的一个框架,用于在智能手机上打造增强现实体验。您可以使用 Unity 的 AR Foundation 构建跨平台 AR 应用。

构建内容

在此 Codelab 中,您将使用 AR Foundation 构建一个简单的游戏。游戏的目标是使用手持设备控制汽车来收集包裹。

不过,这在完全虚拟的世界中不会发生!您将混合使用物理原子和数字位,通过创建一款能够了解玩家周围环境的游戏,打造一种全新的玩家体验。

完成本 Codelab 后,您的游戏将能够:

  • 检测现实世界中的平面,并在其上绘制比赛场地。
  • 从相机视图投射光线,并检测与平面的相交情况。
  • 根据现实世界中的光照条件做出反应,让游戏更具真实感。

学习内容

  • 如何设置使用 Unity 的 AR Foundation 的项目。
  • 如何使用 ARPlaneManager 订阅新航班。
  • 如何使用 Raycast 查找与虚拟几何图形的交集
  • 如何使用 ARLightEstimationData 为场景打光。

所需条件

2. 设置您的开发环境

在此步骤中,您将准备好环境,以便使用 Unity 的 AR Foundation 进行开发。

确保设备与 AR 兼容

Android 设备上的 AR 体验由 ARCore 提供支持,而 ARCore 适用于支持 ARCore 的设备。确保您的开发设备与 AR 兼容。或者,您也可以使用配置正确的支持 AR 的 Android 模拟器实例

在设备上设置 USB 调试

您需要在设备上启用开发者选项,才能运行调试应用。如果您尚未执行此操作,请参阅 Android 文档,了解如何启用开发者选项和 USB 调试

安装 Unity (2020.3 LTS)

在工作站上,安装 Unity 2020 LTS。在本 Codelab 中,屏幕截图显示的是 2020.3 (LTS) 版 Unity 的界面。其他版本的 Unity 可能也可以使用,但可能需要执行额外的步骤。它可能与此处显示的屏幕截图有所不同。

创建新项目

使用 Universal Render Pipeline 模板创建新项目。为其指定一个描述性名称和一个合适的位置,然后按创建

安装所需的框架

您可以在 Unity Package Manager 中找到 Unity 的 AR Foundation。

  1. 依次点击 Window > Package Manager,打开该窗口。

  1. 在此窗口中,安装您将在本 Codelab 中使用的软件包。如需查看这些框架的最新版本,请使用 图标展开相应条目。为以下每个框架安装最新版本:
    • AR Foundation
    • ARCore XR 插件

完成后,您的软件包管理器应如下所示:

安装入门级软件包

在此 Codelab 中,我们提供了一个起始软件包,其中包含预制件和脚本,可加快 Codelab 的某些部分,以便您专注于如何使用 AR Foundation。

  1. 打开 Assets > Import Package > Custom Package...,然后打开 starter-package.unitypackage,安装初始软件包。
  2. 在随即显示的窗口中,确保所有内容均已选中。
  3. 点击导入

更改 build 设置

由于应用将在 Android 上运行,因此请将 build 平台更改为 Android:

  1. 依次选择 File > Build Settings
  2. Platform(平台)窗格中,选择 Android
  3. (可选)启用开发 build脚本调试,以便在应用运行时保留调试信息。
  4. 点击切换平台

更改项目设置

需要配置 AR Foundation,以便在启动时初始化 XR 系统。

  1. 依次打开 Edit > Project Settings...,然后点击 XR Plug-in Management 部分。
  2. Android 标签页中,启用 ARCore

  1. 在左侧窗格中,点击播放器部分。
  2. Android 标签页的 Other Settings 下,从 Graphics APIs 中移除 Vulkan

  1. 使用 ARCore 的 AR 必需应用要求最低 API 级别为 24。向下滚动,找到最低 API 级别。将最低 API 级别设置为 24。

添加所需的场景元素

通用渲染流水线模板附带了一些您在本教程中不会使用的游戏对象。

  1. 删除 SampleScene 中的所有游戏对象。

  1. 添加 AR Foundation 对象。在层次结构窗格中右键点击。您可以使用此菜单添加以下内容:
  • XR > AR 会话:此对象用于控制 AR 体验的生命周期。
  • XR > AR 会话原点:此对象可将 AR 坐标转换为 Unity 世界坐标。
  • 光照 > 平行光:提供光源来照亮游戏对象。

层次结构应如下所示:

  1. 展开您在层次结构中创建的 AR Session Origin,然后选择 AR Camera 对象。在检查器中,将其标记更改为 MainCamera

设置渲染

Unity 的通用渲染管线需要进行一项更改才能与 AR Foundation 兼容。

  1. Project 窗格中,依次前往 Assets > Settings,找到 ForwardRenderer 资源。

  1. 选择 ForwardRenderer
  2. 在“Inspector”窗格中,使用 Add Renderer Feature 添加 AR Background Renderer Feature。此组件将在场景中渲染摄像头画面。

验证设置

  1. 确保设备已连接到电源,并且已开启 ADB 调试。
  2. 依次点击文件 > 构建并运行...此操作会将应用上传到您的设备,并在安装完成后启动该应用。
  3. 您应该会在设备屏幕上看到摄像头画面。

在下一步中,您将开始向应用添加功能。

3. 检测现实世界中的平面

现在,基本场景已设置完毕,您可以开始开发游戏了。在此步骤中,您将检测平面并将其绘制到场景中。

添加 ARPlaneManager 组件

ARPlaneManager 会检测 ARPlane,并在设备对环境的理解发生变化时创建、更新和移除游戏对象。

  1. 使用“层次结构”窗格创建一个空的 GameObject
  2. 将其重命名为 Driving Surface Manager。此组件将显示飞机,直到玩家选择一架飞机为止。
  3. 选择新的游戏对象。在“检查器”窗格中,点击 Add Component 以添加 AR Plane Manager

  1. 通过设置 Plane Prefab 字段来配置 ARPlaneManager
    1. 点击 None 旁边的按钮,以显示选择游戏对象窗口。
    2. 选择资产标签页,然后搜索 Driving Surface Plane

此预制件来自初始软件包,提供粗糙的地面纹理,将用作平面装饰。

  1. Detection Mode 更改为 Horizontal。此配置会将 ARPlaneManager 配置为仅提供水平平面,非常适合在驾驶时使用。

添加 ARRaycastManager 组件

ARRaycastManager 会公开光线投射功能。在下一步中,我们将使用此对象为用户提供控件。

  1. 确保在“层次结构”窗格中选择了名为 Driving Surface Manager 的对象。
  2. 在检查器中,点击 Add Component(添加组件),将 ARRaycastManager 组件添加到游戏对象。

此组件无需进一步配置。

添加 DrivingSurfaceManager 组件

DrivingSurfaceManager 是 Starter Package 中的辅助脚本,可用于选择 ARPlane。选择 ARPlane 后,所有其他平面都将隐藏,并且新平面将被停用。

  1. 确保在“层次结构”窗格中选择了名为 Driving Surface Manager 的对象。
  2. 在检查器中,点击 Add Component(添加组件),将 DrivingSurfaceManager 组件添加到游戏对象。

此组件无需进一步配置。

运行应用

  1. 点击 File > Build And Run... 以测试所做的更改。
  2. 将设备对准现实世界中的水平表面,然后移动设备,以帮助 ARCore 更好地了解周围环境。

  1. 当 ARCore 检测到平面时,您应该会看到现实世界中的表面覆盖着泥土纹理。ARPlaneManager 会针对检测到的每个平面实例化给定的 Plane PrefabDriving Surface Plane 预制件具有 ARPlaneMeshVisualizer 组件,该组件可为给定的 ARPlane 创建网格。

在下一步中,您将使用检测到的平面作为游戏场地。

4. 针对检测到的平面执行命中测试

在上一步中,您编写了一个可以检测飞机的应用。这些平面会反映在游戏场景中。现在,您将通过创建瞄准线和一辆在检测到的平面上行驶的汽车来添加与这些平面的互动。

创建瞄准线

此应用的控制方案涉及玩家将手机对准某个表面。为了针对指定位置提供清晰的视觉反馈,您将使用瞄准十字线。

为了让此网格线“贴”在 AR 平面上,请使用点击测试。点击测试是一种在特定方向上投射光线时计算交点的技术。您将使用点击测试来检测相机视图方向上的交叉点。

添加十字线

  1. 在屏幕底部附近的 Project 窗格中,依次前往 Assets > Starter Package
  2. Reticle Prefab 拖动到项目的层次结构窗格中,从而将其放置到场景中。
  3. 在层次结构中选择十字线。
  4. 在检查器中,点击 Add Component。添加启动软件包中的 ReticleBehaviour 脚本。此脚本包含一些用于控制瞄准线的样板。
  5. ReticleBehaviour 脚本依赖于您之前创建的 Driving Surface Manager,因此请点击 Driving Surface Manager 选择器来添加依赖项。选择场景标签页,然后选择 Driving Surface Manager

修改 ReticleBehaviour

ReticleBehavior 脚本会将十字线放置在设备视口中心的平面上。

  1. 双击 Script 字段,打开 ReticleBehaviour.cs 脚本。
  2. 使用相机的 ViewToScreenPoint 确定屏幕中心。修改 Update() 方法以添加以下内容:
var screenCenter = Camera.main.ViewportToScreenPoint(new Vector3(0.5f, 0.5f));
  1. 使用此点进行光线投射。添加以下内容:
var hits = new List<ARRaycastHit>();
DrivingSurfaceManager.RaycastManager.Raycast(screenCenter, hits, TrackableType.PlaneWithinBounds);

变量 hits 将包含 ARRaycastHit,用于描述被 ray 相交的可追踪对象上的点。

  1. 通过查询 hits 列表确定地图注点。优先处理 DrivingSurfaceManager 中包含的锁定平面,如果不存在,则使用第一个平面命中。将以下内容添加到 Update() 的末尾:
CurrentPlane = null;
ARRaycastHit? hit = null;
if (hits.Length > 0)
{
    // If you don't have a locked plane already...
    var lockedPlane = DrivingSurfaceManager.LockedPlane;
    hit = lockedPlane == null
        // ... use the first hit in `hits`.
        ? hits[0]
        // Otherwise use the locked plane, if it's there.
        : hits.SingleOrDefault(x => x.trackableId == lockedPlane.trackableId);
}
  1. 如果 hit 包含结果,请将此 GameObject 的转换移至命中位置。
if (hit.HasValue)
{
    CurrentPlane = DrivingSurfaceManager.PlaneManager.GetPlane(hit.Value.trackableId);
    // Move this reticle to the location of the hit.
    transform.position = hit.Value.pose.position;
}
Child.SetActive(CurrentPlane != null);

测试十字线

  1. 点击 File > Build And Run... 以测试所做的更改。
  2. 当您将设备对准某个平面时,您应该会看到十字线跟随摄像头的移动而移动。

创建车辆

玩家将控制一辆玩具车,该玩具车将驶向瞄准线的位置。入门软件包中提供了此汽车的模型和行为。

向场景中添加 CarManager

  1. Hierarchy 中,创建一个新的空 GameObject
  2. 将其重命名为 Car Spawner
  3. 选择您创建的对象。在层次结构窗格中,点击 Add Component 以添加 CarManager 组件。
  4. 点击每个字段的选择器,设置 CarManager 的依赖项:
    • 汽车 Prefab:在 Assets 中,选择 Car Prefab
    • 瞄准线:在场景中,选择 Reticle Prefab
    • 驾驶表面管理器:在 Scene 中,选择 Driving Surface Manager

CarManager 行为会在十字线所在的平面上生成一辆玩具车。如果您愿意,可以查看 CarBehaviour 脚本,了解汽车的编程方式。

试驾

  1. 点击 File > Build And Run 以测试所做的更改。
  2. 点按平面后,您应该会在相应位置看到一辆小汽车。此车辆将跟随十字线。

添加游戏元素

现在,玩家可以控制场景中的实体了,接下来为玩家提供一个要前往的目的地。

  1. 在层次结构中创建一个新的空 GameObject
  2. 将其重命名为 Package Spawner
  3. 选择您创建的对象。在层次结构窗格中,点击 Add Component 以向其添加 PackageSpawner 组件。
  4. 点击每个字段的选择器,设置 PackageSpawner 的依赖项:
    • 软件包预制件:在 Assets 中,选择 Package Prefab
    • 驾驶表面管理器Scene 中,选择 Driving Surface Manager

如果锁定 ARPlane 上还没有软件包,此 PackageSpawner 行为会在锁定 ARPlane 上的随机位置生成一个新软件包。

测试游戏

  1. 点击 File > Build And Run 以测试所做的更改。2. 创建车辆后,应生成一个包裹。
  2. 开车前往包裹所在位置。
  3. 新的一个会出现在随机位置。

5. 设置光照估计

现在,基本游戏已完成,接下来为 AR 场景添加一些真实感。在此步骤中,您将使用 ARCore 的光照估测 API 根据传入的相机帧检测现实世界中的光照。此信息将用于调整场景的照明,使其与现实世界的照明相匹配。

启用光照估计

  1. Hierarchy 中,展开 AR Session Origin,然后选择 AR Camera 对象。
  2. Inspector 中,展开 AR Camera Manager 脚本。
  3. 光照估计字段更改为所有内容

修改定向光

  1. 层次结构中,选择 Directional Light 对象。
  2. 向其中添加 LightEstimation 组件。此组件来自初始软件包,提供了一些用于订阅光照变化的样板代码。
  3. FrameReceived() 函数中,添加:
ARLightEstimationData lightEstimation = args.lightEstimation;

if (lightEstimation.averageBrightness.HasValue)
    Light.intensity = lightEstimation.averageBrightness.Value;

if (lightEstimation.averageColorTemperature.HasValue)
    Light.colorTemperature = lightEstimation.averageColorTemperature.Value;

if (lightEstimation.colorCorrection.HasValue)
    Light.color = lightEstimation.colorCorrection.Value;

if (lightEstimation.mainLightDirection.HasValue)
    Light.transform.rotation = Quaternion.LookRotation(lightEstimation.mainLightDirection.Value);

if (lightEstimation.mainLightColor.HasValue)
    Light.color = lightEstimation.mainLightColor.Value;

if (lightEstimation.mainLightIntensityLumens.HasValue)
    Light.intensity = lightEstimation.averageMainLightBrightness.Value;

if (lightEstimation.ambientSphericalHarmonics.HasValue)
{
    RenderSettings.ambientMode = AmbientMode.Skybox;
    RenderSettings.ambientProbe = lightEstimation.ambientSphericalHarmonics.Value;
}

测试更改

  1. 点击 File > Build And Run 以测试所做的更改。
  2. 查看场景中的对象时,您可能会注意到,这些对象的颜色会根据环境光照而变化。
  3. 如果可能,请尝试调整光线。例如,尝试关闭您所在房间的灯。您应该会看到对象上的光照会根据现实世界中的光照变化而变化。

6. 小结

恭喜!您已完成本 Codelab(有关 Unity AR Foundation)。

所学内容

  • 如何使用 Unity 的 AR Foundation 和通用渲染管线设置基本项目。
  • 如何使用 ARPlaneManager 订阅新航班。
  • 如何使用 Raycast 查找与虚拟几何体的交集。
  • 如何使用 ARLightEstimationData 为场景打光。

后续步骤

奖励作业

如果您想在此处创建的游戏的基础上进行扩展,可以考虑以下想法:

  • 通过在 PackageManager 生成新软件包时修改 TextMeshPro,向游戏中添加得分计数器。
  • 通过启用性能叠加层,可在游戏运行时查看性能信息。
  • 首先使用持久射线投射在场景中放置新对象。当在该区域检测到平面时,该对象将更新为对准该平面。