使用 Unity 的 AR Foundation 创建 AR 游戏

使用 Unity 的 AR Foundation 制作 AR 游戏

关于此 Codelab

subject上次更新时间:6月 25, 2021
account_circleDereck Bridie 编写

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 调试

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

安装 Unity (2020.3 LTS)

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

创建新项目

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

安装所需的框架

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

  1. 依次点击 Window > Package Manager 打开它。

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

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

安装入门套件

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

  1. 依次打开 Assets > Import Package > Custom Package... 并打开 starter-package.unitypackage,以安装入门资源包。
  2. 在弹出的窗口中,确保选中所有内容。
  3. 点击导入

更改构建设置

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

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

更改项目设置

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

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

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

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

添加所需的场景元素

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

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

  1. 添加 AR 基础对象。右键点击 Hierarchy 窗格。您可以使用此菜单添加以下内容:
  • XR >AR 会话:此对象可控制 AR 体验的生命周期。
  • XR > AR 会话原点:此对象会将 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 Plane Manager

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

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

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

添加 ARRaycastManager 组件

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

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

此组件无需进一步配置。

添加 DrivingSurfaceManager 组件

DrivingSurfaceManager 是起始包中的辅助脚本,可用于选择 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. 在 Inspector 中,点击 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. 依次点击 File > Build And Run... 以测试所做的更改。
  2. 将设备对准飞机时,您应该会看到十字线会跟随摄像头的移动。

创建汽车

玩家将控制一辆玩具车,该车会朝着准星的位置行驶。入门套件中提供了此车辆的模型和行为。

向场景添加 CarManager

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

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

试驾

  1. 依次点击 File > Build And Run 以测试所做更改。
  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. 依次点击 File > Build And Run 以测试所做更改。2、创建汽车后,系统应会生成一个软件包。
  2. 驾车前往包裹所在位置。
  3. 系统会在随机位置显示一个新的验证码。

5. 设置光照估算

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

启用光照估计

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

修改方向光

  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. 依次点击 File > Build And Run 以测试所做更改。
  2. 查看场景中的对象时,您可能会注意到它们的颜色会因环境光线而异。
  3. 如果可能,请尝试调整光线。例如,尝试关掉您所在房间的灯。您应该会看到对象的光照会适应真实光照的变化。

6. 小结

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

所学内容

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

后续步骤

奖励分配

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

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