使用 Unity 的 AR Foundation 创建 AR 游戏

1. 概览

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

构建内容

在此 Codelab 中,您将使用 AR 基础构建一个简单的游戏。游戏的目标是使用你通过手持设备操控的汽车收集包裹。

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

学完此 Codelab 后,您的游戏将能够:

  • 检测现实世界中的飞机,然后在飞机上绘制一个游戏场。
  • 投射镜头视野的光线,并检测与平面的相交点。
  • 根据真实的光照条件做出反应,为游戏增加真实感。

学习内容

  • 如何设置使用 Unity 的 AR Foundation 的项目。
  • 如何使用 ARPlaneManager 订阅新飞机。
  • 如何使用 Raycast 查找具有虚拟几何图形的交叉路口
  • 如何使用 ARLightEstimationData 为场景打光。

所需条件

2. 设置您的开发环境

在此步骤中,您将借助 Unity 的 AR Foundation 为开发环境做好准备。

确保您的设备与 AR 兼容

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

在您的设备上设置 USB 调试

您需要在设备上启用开发者选项才能运行调试应用。请参阅关于启用开发者选项和 USB 调试的 Android 文档(如果您尚未这样做)。

安装 Unity (2020.3 LTS)

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

创建新项目

使用通用渲染管线模板创建一个新项目。为其指定一个描述性的名称和相应的位置,然后按创建

安装所需的框架

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

  1. 点击窗口 >软件包管理器

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

完成上述操作后,软件包管理器应如下所示:

安装入门软件包

对于此 Codelab,我们提供了一个包含预制件和脚本的入门软件包,这些软件包会帮助您加快此 Codelab 的某些部分,以便您专注于如何使用 AR 基础。

  1. 打开 Assets >导入软件包 >Custom Package... 并打开 starter-package.unitypackage
  2. 在弹出的窗口中,确保选中所有内容。
  3. 点击导入

更改构建设置

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

  1. 打开文件 >Build Settings
  2. Platform 窗格中,选择 Android
  3. (可选)启用开发构建脚本调试,以便在应用运行时保留调试信息。
  4. 点击 Switch Platform

更改项目设置

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

  1. 打开编辑 >项目设置...,然后点击 XR 插件管理部分。
  2. Android 标签页中,启用 ARCore

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

  1. 使用 ARCore 的 AR 必备应用至少需要 API 级别 24。向下滚动并找到 Minimum API Level(最低 API 级别)。将最低 API 级别设置为 24。

添加所需的场景元素

通用渲染管线模板包含一些您不会在本教程中使用的游戏对象。

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

  1. 添加 AR 基础对象。右键点击 Hierarchy 窗格。使用此菜单可添加:
  • XR >AR 会话:此对象可控制 AR 体验的生命周期。
  • XR >AR Session Origin:此对象可将 AR 坐标转换为 Unity 世界坐标。
  • 光 >定向光:此模式可提供照射游戏对象的光源。

您的层次结构应如下所示:

  1. 展开您在层次结构中创建的 AR 会话来源,然后选择 AR 相机对象。在检查器中,将其标记更改为 MainCamera

设置呈现

Unity 的通用渲染管线只需进行一项更改,即可与 AR Foundation 兼容。

  1. Project 窗格中,浏览 Assets >Settings 中找到 ForwardRenderer 资源。

  1. 选择 ForwardRenderer
  2. 在“Inspector”窗格中,使用 Add Renderer Feature 添加 AR 后台渲染程序功能。此组件会在场景中渲染相机画面。

验证设置

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

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

3. 检测现实世界中的飞机

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

添加 ARPlaneManager 组件

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

  1. 使用 Hierarchy 窗格,创建一个空的 GameObject
  2. 将其重命名为 Driving Surface Manager。此组件会显示平面,直到玩家选择其中某个平面。
  3. 选择新的游戏对象。在“Inspector”(检查器)窗格中,点击 Add Component(添加组件)以添加 AR 平面管理器

  1. 通过设置 Plane Prefab 字段来配置 ARPlaneManager
    1. 点击 None 旁边的按钮,以调出 Select GameObject 窗口。
    2. 选择 Assets 标签页,然后搜索 Driving Surface Plane

入门套装中的这个预制件提供粗糙的地板纹理,可以用作飞机装饰。

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

添加 ARRaycastManager 组件

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

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

无需对此组件进行进一步配置。

添加 DrivingSurfaceManager 组件

DrivingSurfaceManager 是 Starter Package 中的帮助程序脚本,支持选择 ARPlane。选择 ARPlane 后,系统将隐藏所有其他平面,并停用新平面。

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

无需对此组件进行进一步配置。

运行应用

  1. 点击文件 >“Build & Run...”(构建和运行...)测试您的更改。
  2. 将设备对准真实的水平表面,然后四处移动您的设备,以改进 ARCore 对现实世界的理解。

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

在下一步中,您将使用检测到的平面作为竞争环境。

4. 对检测到的飞机执行点击测试

在上一步中,您编写了一个可以检测平面的应用。这些平面会反映在游戏的场景中。现在,您将创建一条瞄准十字线和一辆汽车,让其在检测到的平面上行驶,从而添加与这些平面的互动性。

创建瞄准十字线

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

为了“坚持”将十字线应用到 AR 平面,请使用点击测试。点击测试是一种技术,用于计算在给定方向投射光线时的交集。您将使用点击测试来检测摄像头视野方向上的交叉路口。

添加十字线

  1. 在靠近屏幕底部的 Project 窗格中,依次转到 Assets >入门套装
  2. Reticle Prefab 拖到场景中的 Hierarchy 窗格中。
  3. 选择层次结构中的十字线。
  4. 在检查器中,点击 Add Component。从入门软件包添加 ReticleBehaviour 脚本。此脚本包含一些用于控制十字线的样板。
  5. ReticleBehaviour 脚本依赖于您之前创建的 Driving Surface Manager,因此请点击 Driving Surface Manager 选择器来添加依赖项。选择 Scene 标签页,然后选择 Driving Surface Manager

修改ReticleBehaviour

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

  1. 双击 Script 字段,以打开 ReticleBehaviour.cs 脚本。
  2. 使用 Camera 的 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. 点击文件 >“Build & Run...”(构建和运行...)测试您的更改。
  2. 当您将设备指向某个平面时,您应该会看到十字线跟随相机的移动。

创建汽车

玩家将控制一辆玩具汽车,让其驶向十字线的位置。入门软件包中提供了这辆车的型号和行为。

向场景添加 CarManager

  1. Hierarchy 中,创建一个新的空 GameObject
  2. 将其重命名为 Car Spawner
  3. 选择您创建的对象。在 Hierarchy 窗格中,点击 Add Component 来添加 CarManager 组件。
  4. 点击每个字段的选择器来设置 CarManager 的依赖项:
    • Car Prefab:在 Assets 中,选择 Car Prefab
    • Reticle:在 Scene 中,选择 Reticle Prefab
    • Driving Surface Manager:在 Scene 中,选择 Driving Surface Manager

CarManager 行为会在显示十字线的平面上生成一辆玩具汽车。如果您需要,请查看 CarBehaviour 脚本,了解汽车的编程方式。

试驾

  1. 点击文件 >构建并运行以测试您的更改。
  2. 点按飞机时,您应该会看到该位置出现一辆小型汽车。这辆车会沿着十字路标行驶。

添加游戏元素

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

  1. 在层次结构中创建一个新的空 GameObject
  2. 将其重命名为 Package Spawner
  3. 选择您创建的对象。在 Hierarchy 窗格中,点击 Add Component 以将 PackageSpawner 组件添加到其中。
  4. 点击每个字段的选择器来设置 PackageSpawner 的依赖项:
    • Package Prefab:在 Assets 中,选择 Package Prefab
    • Driving Surface ManagerScene 中,选择 Driving Surface Manager

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

测试游戏

  1. 点击文件 >构建并运行以测试您的更改。2. 创建汽车后,系统应该会生成软件包。
  2. 开车前往包裹。
  3. 系统会在随机位置显示一个新的验证码。

5. 设置光照估计

基本游戏现已完成,不妨为您的 AR 场景增添些许真实感。在此步骤中,您将使用 ARCore 的 Lighting Estimation API 根据传入的相机帧检测现实世界中的光照。系统会利用这些信息来调整场景的光线,使其与真实环境的光线相符。

启用光照估计

  1. Hierarchy 中,展开 AR Session Origin 并选择 AR Camera 对象。
  2. Inspector 中,展开 AR Camera Manager 脚本。
  3. Lighting Estimation 字段更改为 Everything

修改方向光

  1. Hierarchy 中,选择 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. 点击文件 >构建并运行以测试您的更改。
  2. 观察场景中的对象时,您可能会注意到它们的颜色取决于环境的光线。
  3. 如果可能,请尝试调整光线。例如,尝试关掉您所在房间的灯。您应该会看到对象的光照会适应真实光照的变化。

6. 小结

恭喜!您已在 Unity AR Foundation 中完成此 Codelab 的学习。

所学内容

  • 如何使用 Unity 的 AR 基础和通用渲染管线设置基本项目。
  • 如何使用 ARPlaneManager 订阅新飞机。
  • 如何使用 Raycast 查找具有虚拟几何图形的交叉部分。
  • 如何使用 ARLightEstimationData 为场景打光。

后续步骤

奖励分配

如果你想进一步拓展你在这里制作的游戏,可以参考以下建议:

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