增强现实企业级项目-全-
增强现实企业级项目(全)
原文:
zh.annas-archive.org/md5/ef99724ddd4d350ed6a2857c854fa264译者:飞龙
前言
增强现实(AR)是一项令人惊叹的技术,其历史可以追溯到 20 世纪 90 年代,直到谷歌眼镜的出现和基于 AR 的游戏《精灵宝可梦 GO》的发布,才为公众所熟知。尽管最初它主要用于营销以获得“哇”的效果,但它后来被证明是许多其他领域(如旅游、工业、医学和教育)中用户的自然界面。其功能的多功能性(基于图像或物理世界识别、GPS 定位等)和目标设备(Android/iOS 移动设备、计算机、网络和头戴式显示器(HMD))使其成为不同领域和实施(如工业指南、现场艺术体验和培训工具)的完美补充。
《企业增强现实项目》旨在带您踏上使用市场上最知名的框架开发并构建增强现实(AR)应用的旅程。在这本书中,我们将详细探讨为六个不同的企业领域(制造、培训、营销、零售、自动化和旅游)开发基于 AR 的应用程序,从市场需求出发,并在每种情况下选择最合适的工具。每一章都将通过使用不同的框架或目标设备来介绍 AR 的新用途。
第一章将介绍 AR,以便您在开始编码之前对其用途和潜力有一个良好的理解。接下来,我们将向您介绍 Unity,这是一个惊人的 3D 工具,它将在许多章节中简化集成 AR 框架和操作 3D 对象和场景的任务。然后,我们将使用 Android Studio 和 ARCore 来创建我们的第一个用于原型设计的增强现实项目。之后,我们将探索使用 Google Web Component <model-viewer>的 WebAR,以及新兴的 AR 创作工具 Augmented Class!,用于教育。接下来,我们将开始使用 Unity 来集成 AR 框架 EasyAR,创建一个用于营销体验的 AR 目录。然后,我们将继续使用 Vuforia 框架,并在零售中使用它。此外,我们将使用 Vuforia 结合 AR 眼镜来创建自动化过程的逐步指南。然后,我们将以在 Xcode 中开发的 ARKit 结束本书,以实现一个用于旅游的增强现实维度门户。
本书面向对象
《企业增强现实项目》面向对新兴和交互式技术感兴趣的爱好者,他们希望逐步构建任何领域的 AR 应用程序,并了解开发它们的最新工具。无需具备 AR 经验。一些面向对象的编程技能将有所帮助。
本书涵盖内容
第一章,《AR 简介及其在企业中的应用》,本书首先介绍了 AR 及其应用。它涵盖了技术的起源、可开发的 AR 类型、本书中将要使用的框架,以及 AR 在不同企业领域的应用。
第二章,《Unity AR 开发的简介》,是 Unity 实时 3D 开发平台的介绍,您将学习主要元素的名词和用法。您还将学习如何使用 C#创建第一个脚本,以了解这个工具的潜力。
第三章,《使用 ARCore 进行制造业的 AR》,介绍了 ARCore 技术及其表面检测功能。您将使用 Android Studio 和 Sceneform 插件创建一个 Android 原型查看器,这将帮助我们轻松地将 3D 模型集成到我们的项目中。
第四章,《使用 WebAR 和增强课堂进行培训的 AR》,在共同的项目中探索两种不同的工具。使用 WebAR,您将学习如何开发一个简单的 Web 应用,该应用包含<model-viewer> Web 组件,该组件将用于从支持 ARCore 的移动设备启动 AR。增强课堂!是一个用于 Android 的作者工具,用于轻松创建交互式教育 AR 项目。
第五章,《使用 EasyAR 进行营销的 AR》,为您介绍如何使用 Unity 结合 EasyAR 框架开发 AR 项目。您将学习如何基于图像跟踪开发增强型目录,以及如何在 Unity 中创建界面并将它们链接到场景中的脚本和对象。
第六章,《使用 Vuforia 进行零售的 AR》,教您如何在 Unity 中使用 Vuforia 的地形检测功能将 3D 对象放置在平坦表面上,并对其进行移动/旋转/缩放,同时还有在 Vuforia 之上添加 ARCore 的可能性。在此过程中,您将继续使用 Unity 及其组件来巩固之前的概念。
第七章,《使用 Vuforia 和 AR 眼镜进行自动化 AR》,继续使用 Vuforia 框架进行开发,但在此案例中侧重于 AR 眼镜。在创建自动化过程的增强型指南时,您将了解移动和眼镜导向型应用之间的相似之处和不同之处。
第八章,《使用 ARKit 进行旅游的 AR》,在 Xcode 上开发,针对 iOS 设备。在本章中,您将创建一个锚定在现实世界中的增强型门户,将用户带到隐藏的虚拟世界。为此,您还将学习如何使用 SceneKit 框架创建 3D 场景并显示 3D 模型。
为了充分利用本书
为了充分利用本书,不需要任何先前的 AR 或 Unity 经验,因为它们将在本书中详细讲解。同样,对 Android Studio 和 Xcode 的先了解会有所帮助,但不是必需的。面向对象编程技能会有所帮助,因为我们将使用 Java、C# 和 Swift 来进行我们的项目。然而,如果您遵循书中的步骤并复制粘贴代码,您将能够从头开始构建所有项目。
每一章都将包含安装说明和您实现每个项目所需的信息。
VS: 虽然 VS2019 已经发布,但我们使用 2017 版本,因为它与 Unity 集成,这将确保它可以直接工作而无需进一步配置。
JDK: 任何版本高于 JDK 8 的新 OpenJDK 都应该能够正常工作,但为了避免错误,建议使用版本 8。
下载示例代码文件
您可以从 www.packt.com 的账户下载本书的示例代码文件。如果您在其他地方购买了本书,您可以访问 www.packtpub.com/support 并注册,以便将文件直接通过电子邮件发送给您。
您可以通过以下步骤下载代码文件:
-
在 www.packt.com 上登录或注册。
-
选择支持选项卡。
-
点击代码下载。
-
在搜索框中输入书籍名称,并按照屏幕上的说明操作。
文件下载完成后,请确保使用最新版本解压或提取文件夹:
-
WinRAR/7-Zip for Windows
-
Zipeg/iZip/UnRarX for Mac
-
7-Zip/PeaZip for Linux
本书代码包也托管在 GitHub 上,地址为 github.com/PacktPublishing/Enterprise-Augmented-Reality-Projects。如果代码有更新,它将在现有的 GitHub 仓库中更新。
我们还有来自我们丰富的图书和视频目录的其他代码包,可在 github.com/PacktPublishing/ 上找到。查看它们吧!
下载彩色图像
我们还提供了一份包含本书中使用的截图/图表彩色图像的 PDF 文件。您可以从这里下载:static.packt-cdn.com/downloads/9781789807400_ColorImages.pdf。
使用的约定
本书使用了多种文本约定。
CodeInText: 表示文本中的代码单词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 账号。以下是一个示例:“从它中删除文本,并将按钮名称更改为 Home_button。”
代码块设置如下:
h1 {
text-align: center;
color: #000000;
font-style: bold;
}
粗体: 表示新术语、重要词汇或您在屏幕上看到的词汇。例如,菜单或对话框中的文字会像这样显示。以下是一个示例:“选择 ARCamera,然后在检查器窗口中点击打开 Vuforia 引擎配置。”
警告或重要提示看起来像这样。
小贴士和技巧看起来像这样。
联系我们
我们欢迎读者的反馈。
一般反馈: 如果你对此书任何方面有疑问,请在邮件主题中提及书名,并通过customercare@packtpub.com给我们发送邮件。
勘误: 尽管我们已经尽一切努力确保内容的准确性,但错误仍然可能发生。如果您在这本书中发现了错误,我们将不胜感激,如果您能向我们报告这一点。请访问 www.packtpub.com/support/errata,选择您的书籍,点击勘误提交表单链接,并输入详细信息。
盗版: 如果你在互联网上以任何形式遇到我们作品的非法副本,如果你能提供位置地址或网站名称,我们将不胜感激。请通过copyright@packt.com与我们联系,并附上材料的链接。
如果您有兴趣成为作者: 如果您在某个领域有专业知识,并且您有兴趣撰写或为书籍做出贡献,请访问 authors.packtpub.com.
评论
请留下评论。一旦您阅读并使用过这本书,为什么不在此购买它的网站上留下评论呢?潜在读者可以看到并使用您的客观意见来做出购买决定,Packt 公司可以了解您对我们产品的看法,我们的作者也可以看到他们对书籍的反馈。谢谢!
如需了解 Packt 的更多信息,请访问 packt.com.
第一章:AR 简介及其在企业中的应用
本书是为对新兴和交互式技术感兴趣的爱好者所写,他们从一开始就希望为任何市场领域构建 AR 应用,并了解开发它们的最新工具。不需要先前的 AR 经验。
本书的主旨是通过在不同企业环境中完成一系列项目,向您介绍不同的 AR 框架。虽然不需要特定的编程技能,但希望您具备一定的知识,以便理解每个示例中的代码。一些面向对象的编程技能会有所帮助,但不是必需的。本书是从零开始编写的,因此您将能够逐步跟随任何编码需求。
在本章中,我们将学习什么是增强现实(AR),并简要介绍其历史、类型以及工作原理。我们还将介绍本书中将使用的软件开发工具包(SDKs)。最后,我们将探讨 AR 的应用实例,特别是其在企业内部的应用。本章的主要目标是理解 AR 当前的应用情况,包括市场、技术、设备以及具有多种 AR 识别模式(如目标图像、云标记、基于 GPS、物体或人脸追踪和空间映射)的开发工具。你还将了解本书中将使用的主要 AR 工具及其主要功能的简要介绍。
到本章结束时,您将基本了解 AR 的工作原理及其不同的用途,以便更容易地跟随后续的技术章节。
本章将涵盖以下主题:
-
理解 AR
-
与 AR 协作
-
在企业中使用 AR
理解 AR
AR 是用来描述允许用户通过技术设备(智能手机、平板电脑或 AR 眼镜)的摄像头,通过该设备添加的虚拟图形信息来可视化部分真实世界的技术术语。该设备将虚拟信息添加到现有的物理信息中。通过这种方式,有形的物理元素与虚拟元素相结合,从而在实时中创建增强现实。以下图像显示了 AR 的工作原理:

一个用户在平板电脑上看到 AR 中的 3D 苹果
现在,我们将探讨 AR 的起点,并了解 AR 可以根据其功能如何划分。
简短历史——新现实的起点
AR 不是一项新技术。AR 的起点可以追溯到哲学家、愿景家和电影制作人 Morton Heilig 发明的机器,他在 1957 年开始构建一个原型,其外观类似于 90 年代非常流行的街机视频游戏机。以下图像显示了该原型的示意图:

发明工作原理的图示(此图像由 Morton Heilig 创作)
Morton 将他的发明命名为Sensorama,这是一种投影 3D 图像、添加环绕声、使座椅振动并创造向观众投掷空气的体验。我们今天可以感受到的最相似的经验是在 4D 电影院看电影,但这些体验是在 60 多年前创造的。
1968 年,哈佛电气工程教授 Ivan Sutherland 创造了一种将成为 AR 技术未来关键设备的装置,称为人机载显示(HMD)。与今天我们所知的 AR 眼镜截然不同,这个被称为达摩克利斯之剑的 HMD 是一个巨大的机器,悬挂在实验室的天花板上,当用户被放置在正确的位置时才会工作。在下面的图像中,你可以看到这个发明的外观:

达摩克利斯之剑(此图像由 OyundariZorigtbaatar 创作)
1992 年,波音研究员 Tom Caudell 发明了 AR 这个术语,同时,AR 技术从另外两个作品中得到了推动。第一个 AR 系统来自美国空军工作的 L.B. Rosenberg,这是一个为用户提供如何执行某些任务的建议的设备,类似于虚拟向导。这可以在下面的图像中看到:

左侧的虚拟设备 AR 系统和其右侧的视图(此图像由 AR Trends 创作)
在这个领域的其他研究由哥伦比亚大学领导,那里的一组科学家发明了一种与打印机交互的 HMD。这个设备被命名为Karma(基于知识的维护辅助 AR),它投射一个 3D 图像来告诉用户如何为打印机充电,而不是查阅用户手册。
下面的图表是基于 Milgram 和 Kishino(1994 年)的连续高级计算机界面表示,其中我们可以看到从现实环境到虚拟现实的混合现实(MR)的不同子类别。位于现实环境附近的 AR 分为空间 AR 和透视 AR。然而,21 世纪移动设备的出现允许了一种不同的 AR 版本,我们可以通过设备屏幕和摄像头来显示它:

混合现实及其子类别
现在我们已经介绍了增强现实(AR)的初步概念,接下来让我们学习如何根据用于在现实世界中显示虚拟元素所使用的触发器来对这项技术进行分类。
AR 背后的魔法
AR 可以通过多种方式创建;主要挑战是如何使现实世界与虚拟世界的结合尽可能无缝。根据用于触发虚拟元素在现实世界中出现的触发器,AR 可以分为以下几种:
-
GPS 坐标:我们使用 GPS 坐标、指南针和加速度计来确定用户的精确位置,包括他们正在看的方位点。根据用户指向的位置,他们将看到一些虚拟对象或从同一位置看到的其他对象。
-
黑白标记器:我们使用非常简单的图像,类似于黑白二维码,以在上面投影虚拟对象。这是最早的 AR 示例之一,尽管如今由于有更真实的方式来创建 AR 体验,它们的使用频率较低。
-
图像标记器:我们使用移动设备的摄像头定位预定义的图像(也称为目标或标记),然后在它们上方投影虚拟对象。这种类型的 AR 已经取代了黑白标记。
-
实时标记器:用户使用移动摄像头创建并定义自己的图像,以在其中投影任何虚拟对象。
-
面部识别:通过摄像头,我们捕捉面部运动以执行请求中的某些动作,例如,向虚拟头像做出面部表情。
-
SLAM:即同时定位与地图构建,这项技术通过特征点理解物理世界,从而使 AR 应用能够识别 3D 对象和场景,并即时跟踪世界,叠加数字交互增强。
-
信标:eBeacons、RFID 和 NFC 是使用无线电频率或蓝牙的识别系统,类似于 GPS 坐标,以触发 AR 元素。
现在,你对 AR 是什么以及它的来源有了更好的理解。我们通过查看第一代原型来介绍 AR 的基础知识,并根据触发虚拟图像的元素对不同的 AR 类型进行分类,以便它们出现在屏幕上。下一步是了解与之合作所需的内容。
与 AR 合作
AR 项目需要一些基本元素来履行其功能:
-
数字支持,主要是平板电脑、手机或眼镜。这些将是我们将用来识别我们所看到的内容并将信息融入 AR 的设备。
-
传感器,如摄像头、GPS、3D 扫描仪等,以感知现实。它们通常集成到移动设备中。
-
一种算法或应用程序,用于理解正在观察的现实,并使用相关信息进行解释和显示。
-
数字内容以丰富现实。这是你融入 AR 的所有信息。
结果是一个界面,其中现实通过位于所需空间中的附加信息进行观察。以下小节将介绍不同的 AR 库和 SDK,以及它们的工作原理。
ARToolKit – 第一个 AR 库
ARToolKit 是世界上第一个开源软件库,它允许创建增强现实(AR)应用,在这些应用中,虚拟图像会与现实世界中的物体重叠。它利用视频跟踪功能来实时计算摄像机的位置以及相对于物理标记的朝向。一旦确定了真实摄像机的位置,虚拟摄像机就被放置在相同的位置,并在真实标记上叠加一个虚拟信息层,例如一个 3D 对象。ARToolKit 最初由加藤宏和华盛顿大学 HIT 实验室开发,并于 1999 年首次发布。它目前作为一个开源项目托管在 SourceForge 上,同时 ARToolworks 提供商业许可证:www.artoolkitx.org/。
AR SDK 简介
现在,我们将介绍本书中将使用的 AR SDK。从 ARToolKit 的首次出现以来,AR SDK 已经发生了很大的变化。让我们介绍并描述本书中将使用的不同 SDK,以创建我们自己的 AR 体验:
-
Vuforia
-
EasyAR
-
ARCore
-
ARKit
让我们简要介绍一下它们。
Vuforia
最初由高通开发,目前由 PTC 运营,Vuforia 是最古老且最知名的 AR SDK 之一,也是市场上最稳定和性能最好的软件之一。Vuforia 提供了各种功能,包括 2D 和 3D 跟踪、无标记 AR 以及称为 Vumarks 的标记。它提供了多个示例和额外功能,例如虚拟按钮、运行时图像目标创建和背景视频纹理操作。
EasyAR
一个 AR 引擎,使我们能够以简单的方式创建 AR 解决方案,并提供多种 AR 功能,包括识别和跟踪在现实世界中先前选定的图像(如封面、照片或名片)的位置、旋转和缩放的技术。它允许我们映射真实地点并跟踪其中的物体,并包含定位和跟踪真实 3D 物体的位置和朝向的技术,而不是平面图像和功能,这允许我们在播放 AR 场景时拍摄视频。
ARCore
第一个版本于 2018 年 2 月发布,是 Google 为 Android 和 iOS 创建 AR 应用的平台。它利用不同的功能,如运动跟踪,来估计移动设备相对于真实世界的位置和朝向;环境定位,以找到和跟踪水平表面,如地面、平板电脑或墙壁;以及光估计,将 3D 元素以逼真的方式放置到真实世界中。针对 Android 7.0 及以上版本,市场上并非所有设备都支持这项技术,尽管自第一个 SDK 版本以来,支持该技术的设备数量已大幅增加。
ARKit
苹果公司在 2017 年发布了 ARKit 的第一个版本,与 Xcode 9 和 iOS 11 一起推出,将 AR 引入 iOS 设备。该框架包含在 Xcode 中,使用户能够在现实世界中放置虚拟内容。在官方发布几个月后,它增加了新的功能,如 2D 图像检测和面部检测。2018 年,随着 iOS 12 的发布,ARKit 2 推出,新增了 3D 对象跟踪、为场景添加逼真纹理以及创建多用户 AR 体验等功能。在撰写本书时,最新版本是 iOS 13,ARKit 3 承诺在当前状态下实现巨大改进,因为它将添加一种与虚拟元素交互的新方式,例如在检测到人站在虚拟对象前面时隐藏虚拟对象。它还允许用户通过手势与 3D 对象交互,并不仅捕捉面部表情,还能捕捉人的身体动作。
既然我们已经熟悉了本书中将使用的 AR 工具,让我们看看我们将如何将这些软件应用于不同的企业领域。
在企业中使用 AR
AR 可以在多个领域成为有价值的资产和技术。在本节中,我们将学习它在工业、营销、零售和旅游等领域的应用。在第一种情况下,我们将了解工业 4.0 如何将 AR 置于聚光灯下,因为它是生产、维护、培训等领域人机交互的自然界面。
本节的主要目标是让您在开始编码之前更好地了解如何在自己的项目中应用 AR。这样,您将能够根据自身需求调整本书中的示例。
让我们开始介绍 AR 在工业领域的应用。
在工业 4.0 中使用 AR
这种技术在工业领域的应用正在增长。其应用重点之一是能够为机器的故障做好准备,从而知道哪个部件已经损坏以及如何进行维修。这种 AR 的应用可以显著降低成本,因为它有利于在故障发生之前迅速采取行动。您还可以使用 AR 在实施之前可视化工厂或产品。这意味着您可以在将其变为实体之前完善要构建的内容。AR 在工业领域的应用有利于工业 4.0 的使能技术之一的应用,这些技术有助于提高公司的竞争力和生产力。
以下是一些示例:
-
智能助手
-
虚拟原型
-
物流与仓储管理
-
数字孪生
让我们更详细地看看这些示例。
智能助手
使用 AR 与维护过程管理平台结合,可以为工业机器的操作提供直接支持,从而缩短操作或维修任务的时间并提高准确性。以下是一些在这种情况下可以执行的任务:
-
跟随指导说明和工作流程
-
实时分配活动
-
检查清单和分配任务列表
-
创建干预的数字报告
-
自动检测 3D 对象
-
实时查看 3D 手册和工作单
-
通过视频通话拥有专家远程协作者
-
从机器中提取和显示实时数据
在这种情况下,使用增强现实(AR)技术通过降低成本和错误的可能性来提高商业生产力。
虚拟原型
AR 可以应用于实时可视化和配置 3D 工业工厂和设备。3D 模型可以在进行验证的工业环境中显示,也可以在展览会和活动等展览空间中展示。通过 AR,您可以在设备安装的位置可视化工业机械的全息图,以评估其尺寸、逃生空间和安全边缘。通过这样做,您可以优化生产流程。此外,将重型工业机械从世界的一个部分运送到另一个部分以在展览会上展示,成本非常高。使用 AR,您可以在展位中心看到您的产品就像它是真实的一样。
物流和仓库管理
通过连接到仓库管理系统的 3D 查看器或眼镜,仓库操作员可以直接在设备上接收商品存储的信息,这使得他们能够提高工作效率和质量,最终提高生产率。
数字孪生
多亏了 AR 技术,您可以为真实系统、产品或服务创建一个虚拟和动态的复制品,通过从传感器或自动化中获得的信息,模拟其行为。这样,它允许智能监控和分析,以及在复制品中实现模拟和实验,没有风险或成本,目的是提高真实系统的性能和有效性。
在这本书中,我们将学习如何通过创建一个带有 AR 引导和培训的原型自动化来使用 AR 进行制造。
在其他企业领域使用 AR
行业并不是 AR 技术唯一有价值的领域。这种技术的多功能性使其成为用户与最终产品或过程之间完美的沟通工具,并为它们添加了一个视觉和交互层,以吸引他们的注意力。无论是用来使产品更具吸引力,还是帮助用户通过附加信息理解一个过程,AR 在许多领域都可以成为一项宝贵的资产。让我们看看本书后面将要涵盖的其他企业领域,在这些领域中 AR 增加了价值。
制造业中的 AR
在这个领域,AR 有许多用途,如原型设计、生产和培训。在这些领域,AR 可以通过在现实世界之上可视化设计来帮助加快原型设计并降低成本,允许设计师、工人和潜在客户在模型周围和内部走动,并操纵其三维结构。
AR 用于培训
AR 已成为教育和培训中的一个宝贵资产。它使我们能够在图像上或直接在房间内以三维形式可视化概念,这样我们可以更快、更动态地获取信息(只需用摄像头指向而不是翻阅书籍或在网上搜索信息),或者创建更深入的个人项目(使画作栩栩如生、在手工艺品上添加说明或额外信息、创建动画演示等)。
AR 在营销中的应用
使用 AR,用户负责他们的体验并可以与之互动。现在,品牌已经超越了“哇”的效果,创造了功能性的体验来推广和销售他们的产品。这包括增强型目录,它在其平面图像上以 3D 形式展示产品;虚拟镜子,你可以在 AR 中试戴眼镜或配件;包装变得生动起来,解释制造过程中的元素;等等。
AR 在零售中的应用
零售是 AR(增强现实)提供更广泛可能性之一的领域,从满足和吸引消费者以减少退货产品,到将产品与社交媒体或个性化购物体验相连接。这方面的例子包括在购买前尝试产品,以便用户可以在实际购买产品之前,将衣服、鞋子、眼镜甚至化妆品可视化到自己身上。通过这样做,他们可以借助 AR 看到家具、艺术品甚至墙面涂料在自己家中呈现的效果。
其他例子包括在购买产品之前查看有关产品的额外信息,如评论和评价,从商店接收地理位置信息及折扣,以及在超市或大型商店中,通过区域引导顾客到他们想要的产品。
AR 在自动化中的应用
AR 是自然的人机界面和连接到物联网(IoT)和大数据的桥梁。它允许工人以简单和吸引人的方式可视化并交互工厂机器和传感器的数据,无论是使用移动设备还是 AR 头戴设备。
AR 在自动化中的应用可以从员工的面部识别到访问具体机器,到通过 AR 眼镜进行现场生产过程的实时监控或远程访问和控制。
AR 在旅游中的应用
增强现实吸引人的地方在于它在现实世界之上显示的视觉内容。这使得这项技术非常适合增强旅行体验,从展示天际线信息到让博物馆中的动物栩栩如生,甚至实时翻译标志和指南。在旅游业中,AR 的一些最常见用途包括在陌生城市的街道上充当现场导游,用户可以在 AR 应用显示他们最感兴趣的景点的同时在城市中四处走动;当用户用摄像头指向地图时,在地图上显示景点和兴趣点(POIs);在画作、雕塑或纪念碑上提供各种额外信息,以便当用户指向一幅画时,它可以显示关于作者、画作创作地点和时间或甚至通过 3D 模拟使其栩栩如生的视频。除了所有这些体验之外,当 AR 与其他沉浸式技术(如虚拟世界或 360 度视频)结合时,体验又向前迈出一步,使用户能够同时访问多个地方(例如,在博物馆网络中,在访问其中一个的同时,能够虚拟访问其他地方)。
在本节中,我们探讨了如何在不同领域使用增强现实(AR)的几个示例,从在建造之前可视化原型,到吸引客户或为艺术品增值。现在,你对 AR 在商业世界中的可能性以及如何根据每个行业的需要应用它有了更好的理解。
摘要
在本章中,我们通过学习什么是 AR、它的起源以及我们需要哪些软件和元素来创建它,首次了解了 AR。我们了解了本书中将使用的 SDK 的名称和主要功能,现在我们准备开始创建自己的 AR 项目。
在下一章中,我们将介绍 Unity 3D,这是一个 3D 工具,可以作为几乎所有 AR 项目的基础,因为大多数 AR SDK 都与它兼容。你将了解它是如何工作的,并创建一个简单的示例,这将是后续 AR 项目的基础。
第二章:Unity AR 开发入门
本章将向您介绍 Unity,这是一个实时 3D 开发平台,已成为多平台增强现实(AR)开发的主要工具之一。其多功能性、广泛的文档和活跃的论坛使得学习曲线快速,并且其 Asset Store 中已创建的场景、示例和多样化的资源将帮助您以快速简单的方式创建令人惊叹的 AR 体验。
本章的主要目标是让您在使用 AR 项目之前对 Unity 感到舒适。您将学习如何安装和使用 Unity,了解用户界面的分布,以及主要组件的名称和用途。然后,您将创建一个简单的 C#脚本,以了解脚本编写的强大功能,以便能够自定义 3D 场景。到本章结束时,您将掌握基本知识,以便可以通过集成和与以下章节中将要介绍的 AR软件开发工具包(SDKs)一起工作来进一步探索 Unity。
Unity 是 AR 开发中最强大的工具之一;它是跨平台的,大多数 AR SDKs 都有与 Unity 兼容的特定包。在本书中,第五章,使用 EasyAR 进行营销的 AR,第六章,使用 Vuforia 进行零售的 AR,和第七章,使用 Vuforia 和 Epson 眼镜进行自动化的 AR,将使用 Unity 开发,尽管它们的示例项目是在 Android 设备上实现的,但它们也可以构建(Epson 眼镜除外,它只能在 Android 操作系统上运行)为 iOS 设备,几乎不需要代码更改。此外,第三章,使用 ARCore 进行制造的 AR,和第八章,使用 ARKit 进行旅游的 AR,也可以在 Unity 中实现。
因此,本章的重要性在于,您将学习如何创建 Unity 3D 项目并为特定平台构建它,这将为更复杂的项目奠定基础。
在本章中,我们将涵盖以下主题:
-
介绍 Unity
-
为 Unity 准备您的系统
-
理解 Unity 界面
-
Unity 主要组件
-
脚本编写 – 第一个 C#示例
技术要求
本章的技术要求如下:
硬件(从docs.unity3d.com/2019.1/Documentation/Manual/system-requirements.html):
-
CPU:支持 SSE2 指令集
-
GPU:具有 DX10(着色器模型 4.0)功能的显卡
操作系统:
-
Windows: 7 SP1+,8,10,仅限 64 位版本
-
macOS: 10.12+
-
Linux: 固定在 Ubuntu 16.04,18.04 和 CentOS 7
Android 开发软件:
-
Java 开发工具包(本书中为 1.8.0)
-
Unity 3D(本书中为 2019.1.2f1)
-
Android SDK(包含在 Unity 安装中)
-
Microsoft Visual Studio Community 2017(包含在 Unity 安装中)
本章的资源和相关代码文件可以在以下链接找到:github.com/PacktPublishing/Enterprise-Augmented-Reality-Projects/tree/master/Chapter02。
虽然我们将为 Android 设备开发 Unity 项目,但你也可以为 iOS 构建它们。在这种情况下,要求是 macOS 和 Xcode 9.4 或更高版本。
介绍 Unity
当我们想到近年来对游戏开发产生重大影响的工具时,一个名字脱颖而出:Unity。Unity 是一个图形引擎,帮助我们开发视频游戏、交互式项目、可视化以及在不同平台上进行实时 2D 和 3D 动画。Unity 提供了一个完整的可视化编辑器和脚本,使我们能够创建具有专业完成度的应用程序。
为了这个目的,Unity 由一系列旨在简化设计游戏的不同方面的任务(包括图形、物理、动画和人工智能)的工具包组成。Unity 是一个独特的开发系统,它专注于资产而不是像其他类似的 3D 建模应用程序那样关注代码。游戏内容是从编辑器构建的,游戏则是使用 C# 脚本语言编写的。
Unity 还包括一个地形编辑器,你可以在这里使用可视化工具、绘画或纹理创建地形(例如空白纸张),还可以添加从 3D 应用程序(如 Blender、3ds Max 和 Maya)导入的其他元素。
Unity 在市场上迅速增长,并因其某些特性而被公司和专业人士采用,这些特性使 Unity 在其他游戏引擎中脱颖而出:
-
Unity 是一个多平台工具,允许我们为多个平台发布 2D 和 3D 内容,例如 Windows、OS X、GNU/Linux、Flash、Xbox One、PS4、Nintendo Switch、Android 和 iOS,包括基于 Web 图形库(WebGL)技术的网络游戏(这是一个在任何网络浏览器中渲染 3D 图形的标准规范)。
-
Unity 为学习和独立开发者提供了一套完整的免费许可证,以及根据开发者公司业务量不同而具有不同可扩展定价计划的许可证。
-
Unity 是最受欢迎的 AR 和 虚拟现实(VR)开发引擎之一,从早期就支持行业发展。市场上三分之二以上的 AR 和 VR 应用都是使用 Unity 开发的。
-
Unity 是一个可扩展的环境,可以通过我们自己的或第三方插件进行扩展,并且以可扩展的方式随着新元素和功能的发展而增长,这些元素和功能并非它最初创建时设计的。
-
Unity 提供了一个门户,我们可以用它来购买和销售各种免费和付费的扩展和资源,称为 Asset Store。这个门户不仅对开发者有用,还让商业市场能够创建特定的公司,这些公司的商业模式是创建工具和内容,以便他们可以在这个在线商店中销售自己的资源。
-
Unity 集成了额外的服务,其中大部分是免费的,使我们能够在不同的视频游戏世界的商业模式中产生利润。例如,这些服务包括 Unity Ads,允许您添加广告;Unity Analytics,提供有关用户互动的信息;以及 Unity Networking,为在线游戏开发提供基础设施。
现在我们已经了解了 Unity 是什么以及它的众多特性,我们可以开始准备我们的系统,以便安装必要的软件。
为 Unity 准备您的系统
在这本书中,我们将使用 Unity 来开发 Android 移动应用程序。为了创建 Android 应用程序,我们需要安装Java 开发工具包(JDK)和 Android软件开发工具包(SDK)。
正如我们在技术要求部分提到的,如果我们在一个运行 macOS 计算机上的 Xcode 上运行 Unity,我们可以轻松地运行相同的项目用于 iOS。
由于 Unity 直接提供 Android SDK 安装,我们将首先安装 JDK,然后继续在我们的计算机上安装 Unity。
安装 Java 开发工具包(JDK)
要安装 JDK,请按照以下步骤操作:

-
确保您接受 Java SE 的二进制代码许可协议。
-
选择最新的 Java SE 开发工具包(在我们的例子中,这是 Java SE 开发工具包 8u201)。
-
下载后,运行安装文件,并让它将 JDK 和 JRE 安装到默认文件夹中。
从 Unity 2019.2 版本开始,Unity 安装允许您在 Android 构建支持选项中安装 OpenJDK(请参阅安装 Unity部分)。
现在您已经安装了 JDK,让我们安装 Unity。
安装 Unity
我们将使用 Unity Hub 安装 Unity,这是一个允许我们在计算机上安装和管理不同版本的 Unity 的工具。您可以从unity3d.com/get-unity/download下载 Unity Hub。
按照以下步骤安装 Unity:
-
下载并安装 Unity Hub。
-
运行 Unity Hub。第一次运行时,它会通知您缺少许可证,如下面的截图所示。点击管理许可证:

无有效许可证信息
- 在许可窗口中,将出现另一条消息,要求你登录以添加许可。点击登录:

许可窗口中的登录消息
- 将会出现一个弹出窗口,要求你输入电子邮件和密码。如果你没有账户,你可以通过点击创建一个账户来创建一个账户。你也可以使用谷歌或 Facebook 登录:

登录 Unity
- 现在,选择一个许可选项,然后点击完成。(如果你符合要求,可以使用个人许可免费使用 Unity。如果不满足条件,你必须在他们的网页上购买 Unity Plus 或 Pro (
store.unity.com)。)

选择产品的许可
- 现在,返回,点击安装选项卡,然后点击添加以添加新的 Unity 安装:

添加新的 Unity 版本
- 在出现的弹出窗口中,选择你想要安装的 Unity 版本和要添加的模块。在我们的例子中,我们使用的是 2019.1.2f1 版本,我们将安装 Microsoft Visual Studio Community 2017 进行编码和 Android 构建支持,以及 Android SDK & NDK Tools 进行 Android 开发,如下面的截图所示:

选择 Unity 版本和模块
Unity Hub 总是显示每个版本的最新编译版本。如果你想安装特定版本,例如我们在这里使用的版本,你可以在 Unity 存档中找到它并通过 Hub 安装:unity3d.com/es/get-unity/download/archive。
从 Unity 2019.2 版本开始,在 Android 构建支持下出现了一个新选项,可以直接安装 OpenJDK。
- 如果你计划使用 Vuforia 进行开发,正如我们在第六章 AR for Retail with Vuforia 和第七章 AR for Automation with Vuforia and Epson Glasses 中将要做的,请检查以下截图中的 Vuforia 增强现实支持选项。然后,点击下一步并完成安装:

选择 Vuforia 增强现实支持
Unity 的最新版本可能并不总是支持 Vuforia。如果你在列表中没有看到 Vuforia,不要慌张!这是因为最新的 Unity 版本还没有支持它,你应该安装一个支持 Vuforia 的旧版本。
- 安装完成后,你将被送回到安装窗口,在那里你会看到新版本和已安装的模块,如下面的截图所示:

新 Unity 版本的安装窗口
- 如果在安装过程中你忘记添加一个模块或者你想稍后添加,你只需点击右上角的三点按钮,然后选择添加模块,如下所示:

安装完成后添加新模块
- 现在,点击“项目”标签页。在这里,我们将通过点击 NEW 按钮来创建一个新的项目,如下所示:

创建新项目
- 我们将创建一个 3D 项目(已经选中)。在设置面板中,给项目命名并设置位置,如下面的截图所示。然后,点击 CREATE:

设置新的 Unity 项目
- 现在,Unity 将打开新项目,你可以开始使用它。如果你关闭 Unity 窗口,你可以通过从 Unity Hub 的项目窗口中选择它来重新打开项目,如下面的截图所示:

新项目出现在项目窗口中
就这样。现在,你已经将 Unity 安装到你的电脑上,你的第一个项目已经打开,你可以开始使用它了。在下一节中,我们将提供 Unity 界面的导游,以便了解 Unity 提供的可能性以及如何使用每个工具。
理解 Unity 界面
第一次打开 Unity 编辑器时,你会看到一个带有不同栏和窗口的布局,类似于以下截图所示:

初始 Unity 布局
初看之下,Unity 的配置略带 3D 建模工具的感觉,中间是 3D 场景,尽管它比建模工具多了几个面板。如果你不熟悉 3D 工具,可能会觉得理解所有内容有些令人畏惧,但 Unity 的界面相当直观,并且在 Unity 各个版本中保持得很一致。前一个截图中所看到的主要组件如下(从左上角到右下角):
-
工具栏:在这里,我们有主要的按钮,以便我们可以在场景视图中操作对象以测试场景。
-
层次结构窗口:层次结构窗口按层次顺序显示场景视图中的元素。
-
场景视图、游戏视图和资产商店窗口:这三个标签页有不同的用途。场景视图显示 3D 场景中的所有元素。游戏视图从摄像机的视角显示场景构建后的样子。资产商店窗口可以用来从 Unity 商店下载包和资产,以便我们可以将它们包含在我们的项目中。
-
检查器窗口:当在层次结构窗口或场景视图中选择一个元素时,其特性和组件将显示在这个窗口中。
-
项目窗口和控制台窗口:前者显示项目中所有目录和文件,我们可以(或不能)在场景中使用,而后者显示日志消息。
现在,我们将详细探讨每个组件,并学习如何根据我们的需求和喜好更改此布局。
工具栏
此工具栏固定在屏幕上,使我们能够访问 Unity 的主要功能。它分为三个部分:用于操作场景中对象的工具、游戏视图控件以及一组按钮,用于访问 Unity 服务和管理图层和 UI 布局:
在左侧,我们可以看到我们可以用来操作场景视图及其上对象的工具。以下是这些工具:
-
手动工具
-
移动工具
-
旋转工具
-
缩放工具
-
矩形工具
-
组合工具
-
中心/旋转点按钮
-
本地/全局按钮:

工具栏左侧的按钮
让我们逐一查看这些工具:
-
手动工具:这是场景的导航工具。它有三个用途:
-
移动:左键点击 + 拖动以在场景中移动而不会更改其任何对象。工具栏和场景视图中出现一个手形图标。
![图片]()
-
环绕:Alt + 左键点击 + 拖动以在场景中环绕。工具栏和场景视图中出现一个眼睛图标。
![图片]()
-
缩放:Alt + 右键点击 + 拖动以在场景中缩放和缩小。工具栏和场景视图中出现一个放大镜图标。
![图片]()
-
您可以通过按鼠标滚轮并拖动来随时使用移动功能。您还可以使用鼠标滚轮进行缩放和缩小。
- 移动工具:当选择此按钮时,您可以通过拖动相应的箭头将场景中的对象移动到三个轴上。您还可以拖动出现在箭头交点上的小正方形,将对象移动到平面(两个轴)而不是单个轴上:

移动 3D 元素
- 旋转工具:当选择此按钮时,您可以通过拖动相应的圆圈在三个轴上旋转场景中的对象:

旋转 3D 元素
- 缩放工具:当选择此按钮时,您可以通过拖动相应的箭头(以小立方体结束)在三个轴上缩放场景中的对象。您还可以拖动中心立方体以在三个轴上均匀缩放对象:

缩放 3D 元素
-
矩形工具:我们之前看到的工具被认为是用来操作 3D 模型的。然而,矩形工具专门用于场景中的用户界面(UI)元素,并且它在二维空间中工作。在以下屏幕截图中,我们正在操作一个按钮:
- 您可以通过拖动来移动 UI 元素:

移动 UI 元素
-
- 要旋转一个元素,将鼠标悬停在角落直到出现旋转图标。然后,点击并拖动:

旋转 UI 元素
-
- 您可以通过从角落拖动来缩放元素:

缩放 UI 元素
- 组合移动、旋转和缩放工具:此按钮组合了移动、旋转和缩放选项:

所有引导线一起出现以操纵对象
- 中心/轴点按钮:当选择中心时,平移、旋转和缩放操作将从对象的中心点执行。在以下截图中,相机和方向光被选中,引导线出现在结果组的中心点。在这种情况下,相机和灯光将围绕该中心点旋转:

中心选项已激活
当选择轴点时,操作将从每个轴点执行。在这种情况下,相机和灯光将围绕各自的轴点旋转:

轴点选项已激活
- 本地/全局按钮:当选择本地时,平移、旋转和缩放操作将相对于所选对象的起点执行。在以下截图中,灯光被旋转,其坐标系也相应旋转:

本地选项已选择
当选择全局时,操作将相对于世界原点执行:

全局选项已选择
在工具栏的中心,我们有播放、暂停和步进按钮,我们可以使用它们来控制游戏视图:

中心位置的按钮
在右侧,我们有几个按钮,我们可以使用它们来访问 Unity 协作服务、Unity 云服务(云图标)、我们的 Unity 账户、图层可见性菜单和布局菜单。我们将在本节后面使用布局菜单来为我们的项目创建自定义布局:

右侧的按钮
现在我们已经看到了工具栏的功能,让我们看看场景视图。
场景视图
场景视图是您将与当前场景以及您在上面创建的 3D 世界交互的窗口。在这里,您将拥有构成场景的所有内容,您将能够使用工具栏上的命令直观地操纵它们。使用此视图,我们可以导航整个场景,从所有角度查看它,以便我们可以放置 3D 对象并确保它们处于正确的位置。在此视图中,我们还可以操纵 UI 元素。在这个窗口中,我们想要讨论的主要元素是 Gizmo,它位于窗口的右上角。
Gizmo:您可以使用 Gizmo 快速更改视图(顶部、底部、右侧、左侧、前视图、后视图)并在透视和等距(正交)模式之间切换。在更改视图时,Gizmo 中的x、y和z箭头将指向每个轴的方向:

前视图、顶视图和右视图上具有不同箭头的 Gizmo
视图名称左侧的小图标显示它是一个透视或等距(正交)视图,如下面的屏幕截图所示。您可以通过单击小图标在它们之间切换:

透视和等距(正交)视图允许我们调整场景中的对象
现在,让我们来看看层级窗口以及它是如何工作的。
层级窗口
这个窗口是场景视图中元素的分层视图,这些元素通过它们的名称来表示。在顶部,我们始终会有场景,并且我们添加到场景中的所有对象都将悬挂在它上面。在下面的屏幕截图中,我们有不同的元素,其中一些元素(立方体、画布)包含更多的元素。
分层视图使我们能够轻松找到元素及其之间的关系(父子关系),这些关系会影响它们的行为方式。例如,如果我们移动立方体元素,它的子对象 ChildOfCube 将随之一同移动。然而,如果我们只想移动 ChildOfCube 元素,我们会在层级窗口中选择它并移动它,而不会影响其父对象立方体。在上一节中我们解释的局部/全局定位方面,子对象的局部位置、旋转和缩放将相对于父对象:

在层级窗口和场景视图中选中的立方体对象
我们还将使用此窗口通过右键单击并选择我们想要添加到场景中的元素来快速添加新元素。
另一方面,可以通过在场景视图中或层级窗口中单击对象来选择场景中的对象。当对象有多个子对象时,后者非常有用,因为我们可以确保我们选择了正确的元素。在场景视图中,它们可能会重叠。
一个小技巧:在层级窗口中双击对象的名称可以使场景缩放到该对象。
场景视图和层级窗口是我们可以使用来操作场景中元素的两个窗口,即我们将构建到我们的设备中的元素。现在,我们将学习当场景中的一个元素被选中时,检查器窗口是如何工作的。
检查器窗口
此窗口显示当前选中对象的属性和组件。从这里,你可以编辑、删除和向对象添加新组件。由于场景中的不同对象将具有不同的属性,检查器窗口将相应地改变,以在每个时刻显示对应的信息。此窗口可以在以下屏幕截图中看到:

主摄像机和立方体的两个不同的检查器窗口
如前一个屏幕截图所示,场景中的每个元素都将有一个变换组件,以便它可以移动、旋转和缩放场景中的该元素。然而,除了这个之外,图像中的主摄像机和立方体元素没有更多共同的组件。对于摄像机来说,它有一个预期的摄像机组件,而立方体有一个网格、一个渲染器(用于可视化对象)和一个标记该对象物理边界的碰撞器。
检查器窗口中的组件可以被最大化或最小化,这样我们就可以组织视图。这样,如果我们有一个 GameObject 中有许多组件,我们只看到在每一时刻所需的那些。为此,我们可以使用每个组件旁边的小箭头,如以下屏幕截图所示,其中相同的 Main Camera 已将其组件折叠:

主摄像机及其组件已折叠
现在,让我们看看项目窗口是如何工作的。
项目窗口
此窗口显示了项目中所有可用的资产。当你将新资产导入到项目中时,它将出现在此窗口上,从这里,你可以将其拖动到你的场景中。这是一个层次视图,文件按文件夹组织:

显示资产文件夹中主要文件夹的项目窗口
重要! 在构建应用程序时,并非项目窗口中出现的每个资产都会被构建进去。除了一些特殊文件夹,可以在以下位置找到:docs.unity3d.com/Manual/SpecialFolders.html。只有当资产与场景连接时(直接出现在场景上、通过脚本调用等),它们才会被包含在最终的包中。
现在,我们将看看游戏视图,正如我们在本节开头提到的,它位于场景视图旁边的标签中。
游戏视图
此窗口显示了场景是如何由你世界中的摄像机(们)渲染的。你可以使用工具栏中的播放、暂停和步进按钮来播放你的场景,并查看发布后的外观:

从主摄像机对象的视角看,按钮和立方体对象
重要!在播放模式下所做的任何更改都是临时的,并且将在您再次点击播放按钮退出此模式时消失。当您想尝试不同的方法(例如,对象旋转或颜色)以选择适合您的方法时,这很有用,但请确保您没有丢失重要的工作,因为您忘记关闭播放模式了!
此窗口旁边的标签是资产商店窗口。让我们看看。
资产商店窗口
此窗口连接到 Unity 资产商店,这是开发者和设计师上传他们的资产的地方。您可以从此窗口下载并导入资产商店中的任何资产到您的项目中:

Unity 中的资产商店窗口
资产商店提供免费和付费内容,如 2D 和 3D 模型和场景、音频文件、模板、完整项目等,您可以直接将这些资产下载并导入到您的项目中。所有这些资产都使创建项目的过程更加容易和快速。
最后但同样重要的是,让我们学习控制台窗口的工作原理及其用途。
控制台窗口
在这里,您可以找到您项目的日志。此窗口显示有关项目的警告、错误和信息日志,如下面的截图所示。如果您在调试错误代码时遇到困难,Unity 论坛([forum.unity.com/](https://forum.unity.com/))是一个非常有用的工具,您可以搜索类似案例并寻求帮助:

显示不同类型信息、警告消息和错误的控制台窗口
本窗口的主要元素及其功能如下:
-
清除按钮移除所有消息(除了编译错误)。您必须在更改当前场景或播放它之前纠正这些错误。
-
您可以使用折叠功能将相同的消息合并成一条消息行。
-
使用“在播放时清除”来删除您在工具栏上点击播放按钮时产生的所有消息。
-
错误暂停允许在发生错误时暂停场景的执行。
-
使用右侧的三个按钮来显示/隐藏不同类型的消息(信息、警告和错误)。
到目前为止,你应该已经对 Unity 界面的工作方式有了相当的了解。然而,在继续之前,我们将学习如何更改布局配置。根据我们的需求和喜好自定义各种窗口既简单又实用。
更改布局
现在我们已经了解了主要窗口及其功能,我们将首先做的是调整这些窗口在屏幕上的布局,以便它们符合我们项目的需求。对于这本书,我们将使用 2 比 3 布局的修改版,这将允许我们同时看到 AR 场景和游戏。然而,一旦你熟悉了 Unity 的使用,你可以自由选择最适合你的布局。
对于修改后的版本,请按照以下步骤操作:
- 首先,在工具栏右上角的下拉菜单中选择 2 比 3 布局,就在检查器窗口上方:

在布局下拉菜单中选择 2 比 3
- 然后,拖动项目窗口,使其位于层次窗口下方:

将项目窗口拖动到层次窗口下方
- 通过将底部的滚动条拖到最左边来选择项目窗口上的列表视图:

将水平滚动条移到左边
- 创建一个名为
1280 x 720的新游戏视图纵横比,并插入以下值:宽度:1280,高度:720:

创建新的纵横比
- 打开控制台窗口,按 Ctrl + Shift + C 或 Window|General|Console,并将其拖动到游戏视图旁边的标签页:

将控制台窗口拖到游戏视图旁边
- 最后,为了确保每次打开 Unity 时此布局都可用,请转到布局,选择保存布局...,并给它命名:

保存创建的布局
现在,我们已经准备好了布局,可以在我们的 AR 项目中使用。到目前为止,你应该已经熟悉了 Unity 提供的不同窗口和工具以及它们的工作方式。在下一节中,我们将查看在 Unity 项目中可以找到的主要元素。
Unity 的主要元素
在 Unity 中构建的应用程序将由一个项目组成。该项目将包含我们开发应用程序所需的所有必要元素,例如模型、脚本、计划、菜单等等。当你启动 Unity 时,你可以通过指向其根文件夹来打开一个项目。
每个项目包含一个或多个文档,称为场景。在 Unity 中创建的项目被组织成场景,其中场景可以是项目的任何部分。当我们谈论应用程序时,场景可以是开始菜单到任何级别或区域。单个场景将包含许多元素,例如用户界面、3D 对象、脚本等。
你可以在 Unity 项目中找到的一些主要元素如下:
-
资产
-
游戏对象
-
组件
-
脚本
-
预制体
首先,我们将查看资产。
资产
Unity 将用于创建项目的文件称为资产。它们是 Unity 项目中的构建块,可以是图像文件、3D 模型、声音文件、代码文件等形式。Unity 中的资产,如材质、纹理、动画或脚本,可以通过在顶部菜单栏中点击 Assets|Create,或者在项目窗口中的文件夹上右键单击并选择 Create 来在项目中创建。
当我们处理外部资产时,例如从互联网下载的图像或我们设计的 3D 模型,我们可以通过将它们从外部文件夹(例如,从 Windows 资源管理器中的一个文件夹)拖动到项目窗口中的一个文件夹,或者在项目窗口中的文件夹上右键单击并选择 Import New Asset...,将它们添加到项目中。
使用以下方法之一将来自您计算机相册的两个图像添加到项目的Assets文件夹中(我们现在将使用一个,稍后使用另一个),如图所示:

向项目中添加图像
另一种导入资产的方法是通过 Import-Package 导入包含多个资产的整个包。这个选项可以在菜单栏的 Assets 菜单中找到,或者在项目视图中右键单击。
要从项目中删除资产,右键单击它并按 Delete。重要的是要注意,一旦从项目中删除了资产,就无法再恢复它。
现在,让我们看看什么是 GameObject。
GameObjects
当一个资产在场景中使用时,它就变成了一个 GameObject。可以通过在顶部菜单栏中点击 GameObject,或者在场景视图或层次结构窗口中右键单击来将 GameObject 添加到场景中。
使用以下方法之一将 3D Object|Cube 添加到场景中,并将其移动到主摄像机前面,在游戏视图中可见:

在层次结构窗口中创建一个立方体
现在,让我们谈谈组件。
组件
组件有不同的形式,它们负责为 GameObject 添加功能。它们可以用来创建行为(例如,脚本),定义 GameObject 的外观(例如,渲染器),并影响项目中对象功能的其他方面。
所有的 GameObject 都至少包含一个组件。我们从 Transform 组件开始。这个组件负责告诉 Unity 引擎一个对象的位置、旋转和缩放。其他常见的组件元素包括 Renderer 和 Collider。我们将在本书接下来的章节中探讨它们的使用。
通过选择对象然后点击菜单栏上的 Component 菜单,或者在检查器窗口上点击 Add Component 按钮,将组件添加到 GameObject 中。
组件也可以从项目窗口拖动到游戏对象(例如,您可以从项目窗口将脚本拖动到场景视图中的立方体上,脚本将自动出现在检查器窗口中)。
将之前添加到项目窗口中的其中一个图像拖动到场景视图的立方体中,将其转换为纹理:

以图像作为纹理的场景中的立方体
现在我们已经了解了项目中的可见元素,让我们来谈谈不可见的元素:脚本。
预制体
预制体是具有自定义属性和组件的游戏对象(例如,添加了脚本来使其闪烁的光源),您可以将它们存储在项目窗口中,以便在不同的场景/时刻中重复使用。它们可以在任何时间(包括运行时)创建或复制,并且每当您更改原始预制体的属性时,除非另有定义,否则所有实例都将自动更新。
脚本
脚本,实际上是一种组件,是 Unity 不可或缺的一部分,因为它们定义了项目中不同元素的行为。您可以像操作其他组件一样操作(添加/编辑/删除)脚本。
右键单击项目窗口,然后按 Create|C# Script 创建一个新的脚本并给它命名(例如,CubeHandler.cs):

创建一个新的脚本
在检查器窗口中,您会看到新创建的脚本中包含一些默认代码。我们将在下一节中讨论此代码。现在我们已经了解了 Unity 的不同元素,让我们在下一节学习如何编写脚本。
脚本编写 – C#中的第一个示例
为了了解 Unity 中脚本的所有潜力,我们将查看上一节中创建的脚本CubeHandler.cs。正如其名称所暗示的,我们将向其中添加一些代码来操作场景中的立方体。
双击项目窗口中脚本的名称,在 Visual Studio 中打开它。
如果您在安装 Unity 之前已经在计算机上安装了 Visual Studio,那么在双击脚本时,Unity 可能不会自动检测它。如果是这样,您将不得不转到 Edit|Preferences 并转到外部工具。从那里,选择 Visual Studio .exe 文件的路径:

已将 Visual Studio 分配为外部脚本编辑器的首选项窗口
打开脚本后,您将看到以下自动生成的代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CubeHandler : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
前三行是调用三个引用。前两个是常用集合,而第三个是我们需要的工作与 Unity 引擎的引用。
然后,你有类声明。类的名称必须与.cs脚本相同。默认情况下,通过 Unity 生成的类将继承自MonoBehaviour,这允许我们使用以下两个方法:
-
Start方法会在 Unity 场景生成后立即自动调用,并在第一帧更新之前。因此,当初始化变量时,这个方法很有用。 -
Update方法在每个帧上被调用一次,这意味着该方法内的代码将被重复执行。
让我们尝试添加一些代码来控制场景中的立方体:
- 首先,我们将在类声明之后、
Start方法之前声明一个名为speed的变量:
private float speed;
- 然后,我们将在
Start方法中初始化speed的值:
void Start()
{
speed = 0.5f;
}
- 最后,我们将在
Update方法中使用这个变量来告诉立方体以一定的速度旋转:
void Update()
{
transform.Rotate(Vector3.up * speed);
}
这最后一行访问当前 GameObject 元素的transform组件,该组件负责其位置、旋转和缩放。我们告诉transform组件,我们想要以我们之前设置的速度在垂直轴(Vector3.up)上旋转对象。
- 仅凭脚本本身不会做任何事情,因为它不知道我们指的是哪个对象的
transform。为了告诉脚本我们想要操作场景中的哪些对象,请回到 Unity 编辑器并将脚本拖放到立方体上。确保它在检查器窗口中作为其组件之一出现。这样,我们就告诉脚本我们想要旋转的是立方体。完整的代码应该如下所示:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CubeHandler : MonoBehaviour
{
private float speed;
public Texture2D texture;
// Start is called before the first frame update
void Start()
{
speed = 0.5f;
}
// Update is called once per frame
void Update()
{
transform.Rotate(Vector3.up * speed);
}
}
- 现在,如果你在工具栏上按下播放按钮,游戏视图将显示立方体旋转:

当播放场景时,立方体将开始旋转
- 再次按播放按钮以停止模拟。尝试更改
speed的值,看看它如何影响立方体的旋转速度。
transform组件有点特殊,因为它有自己的名称。要访问任何其他组件,我们需要使用GetComponent<ComponentName>()函数。例如,如果我们想更改立方体的纹理(我们之前拖入的图像),我们可以使用这个函数。负责材质和纹理的组件是Renderer。让我们将以下代码包含到我们的脚本中:
- 首先,在速度定义下方添加以下代码行,它声明了一个
Texture2D类型的变量:
public Texture2D texture;
- 现在,将以下两行代码添加到
Update方法中,该方法位于转换行下方:
if (Input.GetKeyDown(KeyCode.A))
GetComponent<Renderer>().material.mainTexture = texture;
在这里,我们说的是,如果系统检测到A键被按下,对象的Renderer组件的纹理将更改为新的纹理。正如你所见,在这种情况下,我们并没有在Start方法中初始化纹理。相反,我们将其设置为public,并将在 Unity 内部对其进行赋值。
- 返回 Unity 编辑器。你将看到在检查器窗口中脚本组件中已添加了一条新行。要将其他图像分配给它,你可以从项目窗口拖动它,或者点击右侧的圆圈并从项目中选择它:

立方体的最后一个组件是带有新行以选择纹理的脚本
- 现在,再次按下播放。当立方体旋转时,按下A键。你将看到立方体的纹理如何变化:

按下键盘上的 A 键以查看立方体的纹理变化
现在,你已经了解了 Unity 项目背后的所有逻辑,并具备了创建更复杂脚本的基礎。在接下来的章节中,我们将使用脚本来实现诸如在 AR 中显示元素或通过用户界面与用户交互等目的。
摘要
在本章中,我们学习了如何安装 Unity 以及使其工作的必要模块,以便我们可以构建移动应用程序。我们还介绍了 Unity 界面的设计,其主要窗口,以及如何根据我们的需求自定义它们的组成。我们查看了一些主要窗口、它们的工具以及如何使用它们。然后,我们学习了在 Unity 项目中可以找到的主要元素以及如何创建/导入它们。最后,我们通过几行代码创建了我们第一个脚本,以了解我们如何轻松地控制和更改场景中的对象。
在下一章及随后的章节中,我们将使用本章所学的所有元素来生成功能齐全的 AR 项目。
第三章:使用 ARCore 进行 AR 制造
在本章中,我们将使用 Google 的 ARCore 工具创建我们的第一个 AR 项目。本章的主要目标是向您介绍最新且增长最快的 AR 工具之一,ARCore。到本章结束时,您将掌握在 Android Studio 中轻松创建自己的 ARCore 项目的必要技能。同时,我们展示了 AR 在制造中的一个应用,即原型设计。
到本章结束时,您将创建一个原型查看器应用程序,用户可以在平面上放置工业部件、机器等 3D 设计,在它们周围和内部导航,并使用手指进行操作(移动、旋转和缩放)。有了这些知识,您还将能够改进当前项目,并适应该领域的需求。
本章将涵盖以下主题:
-
使用 AR 进行制造
-
探索 ARCore
-
创建原型 AR 查看器
技术要求
本章的技术要求如下:
-
Android Studio(本书中为 Windows 的 3.5.2 版本)。
-
Java 开发工具包(本书中为 1.8.0 版本)。
-
Sceneform 插件(从 Android Studio 内部安装。本书中为 1.13.0 版本)。
-
支持 ARCore 的移动设备(请参阅此处列表:
developers.google.com/ar/discover/supported-devices)。该项目已在三星 Galaxy A5(2017)和 Pocophone F1 上进行了测试。
要安装 Android Studio,Windows 的系统要求如下:
-
最小 RAM 4 GB,建议 8 GB
-
最小可用磁盘空间 2 GB,建议 4 GB
-
最小屏幕分辨率 1280x800
关于其他操作系统的更多详细信息,您可以在本页末尾找到官方要求:developer.android.com/studio。
本章的代码文件可以在此处找到:github.com/PacktPublishing/Enterprise-Augmented-Reality-Projects/tree/master/Chapter03。
使用 AR 进行制造
工业 4.0,也称为第四次工业革命,指的是在工厂内包含数字化和互联工具,涵盖生产过程到维护和培训。尽管这个术语已经存在多年,但在过去几年里,由于增强现实(AR)、虚拟现实(VR)、物联网(IoT)、大数据分析(BDA)、增材制造(AM)、网络物理系统(CPS)和人工智能(AI)等技术的指数级增长(在质量和数量上),这个工业 4.0 概念已经获得了新的维度。
AR 的视觉组件使其成为用户自然的接口,用户可以通过移动设备或智能眼镜接收有关流程的实时信息,访问远程系统以获取额外数据,并控制流程和机器。
在制造业中,AR 有许多用途,例如原型设计、生产和培训。在本章中,我们将介绍原型设计,特别是 AR 如何通过在真实世界中可视化设计来帮助减少原型设计成本。这允许设计师、工人和潜在客户在三维空间中操纵模型,对其进行缩放,与单个部件交互,甚至一起穿越它们。ARCore 是我们可以用作该目的的 AR 工具之一。
探索 ARCore
自 2017 年开始预览,ARCore 的第一个版本于 2018 年 2 月发布,它是谷歌为 Android 和 iOS 创建增强现实应用程序的平台。它利用不同的功能,如运动跟踪,来估计移动设备相对于真实世界的位置和方向,以及环境定位,以找到和跟踪水平表面,如地面、平板电脑或墙壁,以及光估计,以将 3D 元素真实地放置到真实世界中。这些功能的更详细解释可以在developers.google.com/ar/discover/concepts找到。针对 Android 7.0 及以上版本,市场上并非所有设备都支持这项技术,尽管自第一个 SDK 版本以来,支持的数量已经大幅增加。您可以通过此处查看当前支持的设备列表:developers.google.com/ar/discover/supported-devices。
ARCore 应用程序可以在不同的平台上开发,例如 Android Studio、iOS 的 Xcode、Unity3D 和 Unreal Engine。当使用 Android Studio 时,开发者可以将 Sceneform 集成,这是一个 3D 引擎,它可以帮助以比 OpenGL 库更简单的方式集成 3D 环境和模型。我们将在项目中使用这个插件来显示 3D 模型。
当使用 ARCore 开发应用程序时,请确保在您的应用程序中披露:developers.google.com/ar/distribute/privacy-requirements。
对于这个项目,我们将开发一个原型查看应用程序,该应用程序将展示三种不同的引擎模型。我们将在项目中使用的引擎模型是从sketchfab.com/3d-models/rocket-engines-6fba4dbbb9444e99ba68425bcb3a7f70获取的。
既然我们已经了解了 ARCore 的基础知识,让我们开始开发应用程序。
创建原型 AR 查看器
在本节中,我们将开发我们的 AR 查看器以进行原型设计。首先,我们将安装所有必需的软件工具——JDK 和 Android Studio——然后我们将创建我们的 Android 应用程序,学习如何在其中启用和使用 ARCore,以及如何使用 Sceneform 插件来显示 3D 元素。
安装 Java 开发工具包 (JDK)
Android Studio 需要我们安装 JDK。它通常位于 C:\Program Files\Java\jdk_version。如果您还没有安装,请按照以下步骤操作:
-
访问 www.oracle.com 并下载最新的 Java SE 开发工具包。
-
下载完成后,运行安装文件,并让它在其默认文件夹中安装 JDK 和 JRE。
如果在 Android Studio 安装过程中它抱怨找不到 JDK,您可以通过转到开始菜单|计算机|系统属性|高级系统属性,打开高级|环境变量选项卡,并创建一个指向 JDK 文件的 JAVA_HOME 系统变量来解决此问题。
安装 Android Studio
一旦 JDK 安装完成,我们也将对 Android Studio 进行相同的操作,因为它是我们开发 AR 应用的主要平台:
-
从 Android 开发者页面下载 Android Studio:
developer.android.com/studio。 -
使用默认值安装工作室,完成后运行它:

安装完成后启动 Android Studio
- 安装后首次打开它时,Android Studio 设置向导将启动,以帮助您配置工作室的最后几步并下载 Android SDK 组件:

安装 Android Studio 首次运行时会出现设置向导
- 一旦完成,欢迎窗口将会启动:

Android Studio 欢迎窗口
现在我们已经准备好了软件,我们可以开始开发我们的应用程序。
创建应用程序
现在我们已经安装了软件,我们将开始创建我们的 AR 应用。我们首先要做的是启动一个新的 Android Studio 项目,并向其中添加所需的库。按照以下步骤操作:
-
点击“开始一个新的 Android Studio 项目”。
-
选择创建一个空活动:

选择活动类型
- 给项目命名、包名和位置。将最小 API 级别设置为至少 API 24:Android 7.0 (Nougat),因为它是第一个支持 ARCore 的版本。点击完成按钮以启动项目:

新项目的配置参数
下一步我们需要做的是在我们的项目中启用 ARCore。
启用 ARCore
在 AR 项目中,ARCore 可以设置为可选或必需。前者可以在不支持 ARCore 的设备上作为普通应用运行,而后者将只出现在支持 ARCore 的设备的 Google Play 商店中。我们的应用是一个完整的 AR 应用,因此我们将选择第二个选项。为了实现这一点,我们需要修改一些项目文件。让我们开始吧:
- 在项目窗口中,展开
app,然后在manifests文件夹内部打开AndroidManifest.xml文件,如下面的截图所示。如果你想在外部打开清单文件,你可以在app/src/main文件夹中找到该文件:

项目中的 AndroidManifest.xml
- 在
<application>标签之前添加以下行:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera.ar" />
在这两种情况下(ARCore 可选和必需)第一行都是必要的,因为它提供了打开摄像头的权限。第二行指示了 ARCore 的使用,并确保只有支持 ARCore 的设备才能访问应用。
- 现在,在
<application>内部添加以下行:
<application
...
<meta-data android:name="com.google.ar.core" android:value="required" />
</application>
这行代码将 ARCore 设置为必需,并在应用安装时(如果尚未安装)从 Google Play 商店下载和安装 ARCore。
- 打开你的项目
build.gradle文件:

在项目窗口中,找到项目的 build.gradle 文件
- 确保它包括 Google 的 Maven 仓库(它应该在那里;如果不是,请添加它):
allprojects {
repositories {
google()
- 打开你的应用
build.gradle文件:

在项目窗口中,找到应用的 build.gradle 文件
- 现在,将最新的 ARCore 库作为依赖项添加(本书中为 1.13.0):
dependencies {
...
implementation 'com.google.ar:core:1.13.0'
...
}
- 通过点击屏幕右上角的“立即同步”来同步 Gradle,以便使这些更改生效:

同步项目选项以同步项目
如果你打算创建一个既支持又不需要 AR 的应用,启用 ARCore 的步骤将与这里展示的不同。请参阅 developers.google.com/ar/develop/java/enable-arcore 了解你需要做出哪些更改。此外,请注意,你将需要检查运行应用的移动设备是否支持 ARCore。你可以通过查看你的代码来完成这项工作。
现在我们已经启用了 ARCore,让我们介绍 Sceneform。
将 Sceneform 添加到项目
如本章开头所述,Sceneform 是一个 Android Studio 插件,它将帮助我们以比 OpenGL 更简单、更快捷的方式显示 3D 模型。
Sceneform 还提供了 ARFragment 和其他 UX 资源,这些资源在请求摄像头权限并检查 ARCore 是否已安装和更新后,将自动处理 AR 会话,而无需我们在代码中包含这些验证。
在撰写这本书的时候,Sceneform 工具仍然处于测试版阶段。如果您在按照这些步骤操作时遇到任何问题,请访问他们的 GitHub 页面(github.com/google-ar/sceneform-android-sdk)获取更多信息。
要将 Sceneform 导入到您的项目中,请按照以下步骤操作:
-
打开文件|设置。
-
在插件选项卡中,搜索
Google Sceneform Tools (Beta)。在撰写这本书的时候,当前版本是 v1.13.0:

Google Sceneform Tools 插件
- 安装它,然后点击右上角的“重启 IDE”以激活更改:

重启 IDE 按钮
- 安装完成后,打开您的应用程序的
build.gradle文件,并在android部分内添加以下编译选项。如果我们不这样做,当构建我们的ModelRenderable时,将出现错误。这仅在minSdkVersion < 26且我们在创建项目时将最小值设置为24(Android 7.0)时才是必要的:
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
- 在同一文件中,在
dependencies括号内,我们将添加以下implementation行以将 Sceneform 包含到我们的项目中:
dependencies {
...
implementation 'com.google.ar.sceneform.ux:sceneform-ux:1.13.0'
...
}
- 您的应用程序的
build.gradle文件现在应该看起来像这样:

添加了新行的应用程序的 build.gradle 文件
- 现在,为了在您的应用程序中使用 ARFragment,请打开
res/layout文件夹中的activity_main.xml文件,并在视图底部的选项卡中选择文本模式。通过这样做,您可以修改文本中的元素:

activity_main.xml 文件中的文本视图和视觉预览
- 删除
TextView块并添加以下内容:
<fragment android:name="com.google.ar.sceneform.ux.ArFragment"
android:id="@+id/ux_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Sceneform 现在已准备好使用。让我们将我们的 3D 模型导入到项目中。
将 3D 模型添加到项目中
3D 模型,也称为可渲染对象,可以通过不同的方式添加:
-
通过基本形状(球体、立方体等)和材料创建,并通过编程组合以生成更复杂的对象。
-
通过标准 Android 小部件(ViewRenderable)创建。它们在场景中以交互式平面卡片的形式渲染。
-
从其他程序作为 3D 资产导入。支持的格式包括 OBJ、FBX 和 glTF(以及 glb)。动画仅在 FBX 中受支持。
我们将使用第一个选项,并使用 Sceneform 导入一个 .obj 文件。
要将模型导入到我们的项目中,我们必须创建一个外部文件夹来包含模型(这个文件夹不会被编译到最终应用程序中),然后使用 Sceneform 将模型导入到项目中。按照以下步骤操作:
- 通过在项目的
app文件夹上右键单击并选择 New|Sample Data Directory 创建一个sampledata文件夹。

将样本数据目录添加到项目中
如果sampledata文件夹没有自动出现在您的项目中,您也可以从文件资源管理器中手动创建它,在项目的app文件夹内。命名为sampledata,它将在 Android Studio 中显示。
- 从为该项目提供的资源包中,将
engine文件夹复制到sampledata文件夹中:

包含模型及其资源的新的引擎文件夹
现在,我们将通过 Sceneform 导入.obj 文件,将 3D 模型作为资产包含进来。
- 右键点击
engine.obj文件并选择导入 Sceneform 资产:

为我们的.obj 文件选择导入 Sceneform 资产
- 保持默认值不变。这将创建一个位于
sampledata中的 Sceneform 资产(.sfa)文件和一个位于assets文件夹中的 Sceneform 二进制资产(.sfb):

模型的默认导入值
在导入过程中,以下行将自动添加到您的应用build.gradle文件的末尾,由 Sceneform 完成:
sceneform.asset('sampledata/engine/engine.obj',
'default',
'sampledata/engine/engine.sfa',
'src/main/assets/engine')
- 保持 Gradle 同步。当它完成后,将打开两个窗口:一个包含模型描述和 3D 预览的文本文件:

我们新导入的模型的文本视图和预览
最后一步是将所有元素合并到 AR 场景中。
构建 AR 场景
现在我们已经启用了 ARCore 和 Sceneform,并将 3D 模型包含在项目中,让我们添加代码,当检测到平面表面并且用户点击屏幕时,模型将出现在屏幕上。让我们开始吧:
- 从
app/java/com.banana.arprototype打开您的MainActivity.java文件并添加以下导入:
import android.net.Uri;
import android.view.Gravity;
import android.view.MotionEvent;
import android.widget.Toast;
import com.google.ar.core.Anchor;
import com.google.ar.core.HitResult;
import com.google.ar.core.Plane;
import com.google.ar.sceneform.AnchorNode;
import com.google.ar.sceneform.rendering.ModelRenderable;
import com.google.ar.sceneform.ux.ArFragment;
import com.google.ar.sceneform.ux.TransformableNode;
- 在我们的类中,创建以下变量以控制 AR 场景和 3D 模型:
private ArFragment arFragment;
private ModelRenderable modelRenderable;
- 现在,在
OnCreate()方法中,添加ARFragment的初始化:
protected void onCreate(Bundle savedInstanceState) {
...
arFragment = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.ux_fragment);
- 仍然在
OnCreate()方法中,使用ModelRenderable在场景中构建模型,如下代码所示:
ModelRenderable.builder()
.setSource(this, Uri.parse("engine.sfb"))
.build()
.thenAccept(renderable -> modelRenderable = renderable)
.exceptionally(
throwable -> {
Toast toast = Toast.makeText(this, "Unable to
load the model", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
return null;
});
在这里,我们使用Uri.parse从assets文件夹中调用模型。如果无法加载它,将会显示错误信息。
- 最后,仍然在
OnCreate()方法中,当检测到平面表面后用户点击屏幕时,我们将放置模型:
arFragment.setOnTapArPlaneListener(
(HitResult hitResult, Plane plane, MotionEvent motionEvent) -> {
if (modelRenderable == null)
return;
Anchor anchor = hitResult.createAnchor();
AnchorNode anchorNode = new AnchorNode(anchor);
anchorNode.setParent(arFragment.getArSceneView().getScene());
TransformableNode model = new TransformableNode(arFragment.getTransformationSystem());
model.setParent(anchorNode);
model.setRenderable(modelRenderable);
model.select();
});
在这里,当用户点击一个平面并且模型可渲染已成功加载时,将创建一个锚点以保持模型的位置。然后,创建一个新的模型节点并将其附加到它上。
- 现在,您可以在 Android 模拟器或实际设备上运行该应用。要在模拟器中运行它,设备必须满足一些要求,并且您必须手动从 Play Store 在该设备上下载 ARCore(请参阅
developers.google.com/ar/develop/java/quickstart中的“准备您的设备或模拟器”部分)。在这里,我们将通过点击播放图标并选择我们的连接设备来直接在我们的设备上运行该应用:

在物理设备上运行应用
- 这样,应用就会安装在移动设备上。正如我们之前提到的,第一次运行应用时,它会检查是否已安装最新的 ARCore 版本:

ARCore 正在检查 ARCore 的最新版本
- 您必须通过 Google Play 安装它:

安装 ARCore 应用
- 一旦完成这个初始步骤,您将能够完成应用的启动。移动手机/平板电脑,直到检测到平坦表面:

白色圆点形成我们可以放置 3D 对象的平面表面
- 在屏幕上轻触以锚定您的模型:

引擎将出现在相机前方
- 您还可以在移动模型的同时用手指调整模型的大小、旋转和移动,以便从不同的角度观察它。如果您再次点击,将出现一个新的引擎:

多次点击会导致多个实例
在应用中玩耍并熟悉使用它。您会看到,根据设备的容量,平面表面的识别速度会更快或更慢。您还会看到,如果您旋转设备(纵向/横向),模型将消失,因为锚点丢失。因此,现在我们已经有了基本设置,我们将对应用进行一些更改以改进整体性能,并给用户添加更多模型到当前场景的选项。
改进基本应用
一旦我们准备好了基本应用,我们可以做一些事情来改进应用的整体工作:
-
将屏幕方向设置为固定。如果我们将其留在自动旋转模式下,旋转屏幕将导致手机丢失锚点,模型将从屏幕上消失。
-
到目前为止,我们已经看到,对于每一次屏幕点击,都会出现一个新的模型。由于我们使用该应用进行原型设计,我们的想法是只显示一个模型。
-
我们还将更改模型的旋转和大小,以便它在场景中显示得更好。
让我们修改代码以添加这些功能。为此,请按照以下步骤操作:
- 通过在
AndroidManifest.xml中的<application>和<activity>内添加代码来强制屏幕方向为纵向模式:
<activity android:name=".MainActivity" android:screenOrientation="portrait">
这样,屏幕将始终保持在纵向模式,不会自动旋转并丢失锚点,即使用户不小心旋转了手机。
- 如果你使用平板电脑或更喜欢在横幅模式下查看场景,将其更改为以下内容:
<activity android:name=".MainActivity" android:screenOrientation="landscape">
- 为了在屏幕上每次点击只显示一个模型,打开
MainActivity.java并在ArFragment和ModelRenderable变量之后创建以下变量:
private Anchor anchor;
private AnchorNode anchorNode;
private TransformableNode model;
- 然后,在
setOnTapArPlaneListener()内部,在modelRenderable = null检查之后和创建新锚点之前添加以下行,以便释放上一个锚点:
protected void onCreate(Bundle savedInstanceState) {
...
arFragment.setOnTapArPlaneListener(
(HitResult hitResult, Plane plane, MotionEvent motionEvent) -> {
if (modelRenderable == null)
return;
//Remove previous anchor
if (anchor != null)
{
arFragment.getArSceneView().getScene().removeChild(anchorNode);
anchor.detach();
anchorNode.setParent(null);
anchorNode = null;
}
这样,当用户在屏幕的不同位置点击时,模型将 移动 到下一个位置,而不是在每个位置都重复出现。
- 现在,从下面的行中删除
Anchor、AnchorNode和TransformableNode的定义部分,以便它们引用全局变量:
anchor = hitResult.createAnchor();
anchorNode = new AnchorNode(anchor);
...
model = new TransformableNode(arFragment.getTransformationSystem());
- 最后,为了旋转和缩放模型,首先将以下导入添加到
MainActivity.java文件中:
import com.google.ar.sceneform.math.Quaternion;
import com.google.ar.sceneform.math.Vector3;
- 在
arFragment.setOnTapArPlaneListener()方法内部,在setParent()之前添加以下代码:
model.setLocalScale(new Vector3(0.55f, 0.55f, 0.55f));
model.setLocalRotation(Quaternion.eulerAngles(new Vector3(-90,45,0)));
这样,模型将出现在一侧,以便我们可以看到其内部。这可以在以下图片中看到:

旋转状态的引擎
现在我们已经改进了基础知识,让我们添加两个更多原型和一个简单的用户界面,这样我们就可以在它们之间切换。按照以下步骤操作:
-
从本项目的
resources文件夹中,将engine2和engine3文件夹复制到sampledata文件夹中。 -
右键单击每个
.obj文件,并选择导入 Sceneform 资产以创建.sfa和.sfb文件。现在,你的sampledata文件夹应该看起来像这样:

包含新模型的 sampledata 文件夹
你的 assets 文件夹应该包含模型的三个二进制文件:

包含三个二进制文件的资源文件夹
- 从本项目的
resources文件夹中,将每个引擎对应的三个图像复制到res|drawable文件夹中:

包含新图像的 res|drawable 文件夹
- 以文本模式打开位于 res|layout 的
activity_main.xml文件,并添加以下代码:
<LinearLayout
android:orientation="horizontal"
android:paddingLeft="4dp"
android:paddingTop="15dp"
android:paddingRight="4dp"
android:paddingBottom="1dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="@+id/ux_fragment">
在这里,我们使用 layout_constraintBottom_toBottomOf 将其锚定到屏幕底部。
- 如果你处于横幅模式,你可能希望将按钮定位在屏幕的右侧,以便有更多空间进行操作。对前面的代码进行以下更改:
<LinearLayout
android:orientation="vertical"
...
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layout_constraintRight_toRightOf="@+id/ux_fragment">
- 现在,添加三个按钮:
<ImageButton
android:id="@+id/engine1_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:src="img/engine1"
android:background="#7cc53a"
android:layout_weight="1.0"/>
<ImageButton
android:id="@+id/engine2_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:src="img/engine2"
android:background="#40000000"
android:layout_weight="1.0" />
<ImageButton
android:id="@+id/engine3_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:src="img/engine3"
android:background="#40000000"
android:layout_weight="1.0" />
第一个按钮有绿色背景(选中),而其他两个有半透明背景。每个按钮都有其对应的 res|drawable 中的图片。
- 最后,添加
LinearLayout的关闭标签:
</LinearLayout>
- 预览应该看起来类似于以下:

竖屏模式下,左侧是 activity_main.xml 文件的代码,右侧是预览
- 默认情况下,预览处于竖屏模式。要将其更改为横屏,请点击旋转的手机图标并选择横屏:

竖屏模式下,左侧是 activity_main.xml 文件的代码,右侧是预览
- 再次打开
MainActivity.java文件并添加以下库:
import android.widget.ImageButton;
import android.view.View;
- 在前面的代码下方添加三个新的
modelRenderables:
private ModelRenderable modelRenderable2;
private ModelRenderable modelRenderable3;
private ModelRenderable currentRenderable;
我们将使用currentRenderable来找出每一刻哪个可渲染对象是活动的。
- 现在,在变量的末尾添加三个新的图像按钮:
private ImageButton button1;
private ImageButton button2;
private ImageButton button3;
-
将
ModelRenderable.builder()复制并粘贴两次以构建两个新的模型。 -
将它们的
Uri.parse调用分别更改为engine2.sfb和engine3.sfb。 -
在
.thenAccept调用中,将renderables的名称更改为相应的名称。生成的代码应如下所示:
ModelRenderable.builder()
.setSource(this, Uri.parse("engine2.sfb"))
.build()
.thenAccept(renderable -> modelRenderable2 = renderable)
.exceptionally(
throwable -> {
Toast toast = Toast.makeText(this, "Unable to load andy renderable", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
return null;
});
ModelRenderable.builder()
.setSource(this, Uri.parse("engine3.sfb"))
.build()
.thenAccept(renderable -> modelRenderable3 = renderable)
.exceptionally(
throwable -> {
Toast toast = Toast.makeText(this, "Unable to load andy renderable", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
return null;
});
- 在第一个
ModelRenderable.builder()中,修改.thenAccept调用:
.thenAccept(renderable -> currentRenderable = modelRenderable = renderable)
在这里,我们将currentRenderable赋值给第一个renderable。这样,屏幕上最初出现的模型将是第一个引擎(记住我们已将第一个按钮突出显示为选中的按钮)。
- 最后,在
setOnTapArListener()方法中,将modelRenderable更改为currentRenderable:
if (currentRenderable == null)
return;
...
model.setRenderable(currentRenderable);
- 要添加按钮的活动,我们将使我们的
MainActivity实现OnClickListener:
public class MainActivity extends AppCompatActivity implements View.OnClickListener
- 这样,我们可以在
onCreate()方法的底部简化按钮的初始化,如下所示:
button1 = findViewById(R.id.engine1_button);
button2 = findViewById(R.id.engine2_button);
button3 = findViewById(R.id.engine3_button);
button1.setOnClickListener(this);
button2.setOnClickListener(this);
button3.setOnClickListener(this);
前三条线初始化我们的按钮,接下来的三条线在用户点击时进行调用(所有三个情况下的调用相同)。
- 要接收这些点击,创建
onClick()方法:
@Override
public void onClick(View view)
{
switch (view.getId()) {
case R.id.engine1_button:
currentRenderable = modelRenderable;
button1.setBackgroundColor(0xFFA4FF50);
button2.setBackgroundColor(0x40000000);
button3.setBackgroundColor(0x40000000);
break;
case R.id.engine2_button:
currentRenderable = modelRenderable2;
button1.setBackgroundColor(0x40000000);
button2.setBackgroundColor(0xFFA4FF50);
button3.setBackgroundColor(0x40000000);
break;
case R.id.engine3_button:
currentRenderable = modelRenderable3;
button1.setBackgroundColor(0x40000000);
button2.setBackgroundColor(0x40000000);
button3.setBackgroundColor(0xFFA4FF50);
break;
}
model.setRenderable(currentRenderable);
}
此方法将在onCreate()之后根据哪个按钮被按下,将不同的modelRenderable分配给currentRenderable并突出显示其对应的按钮。最后一行将当前可见的模型切换到新选中的模型。
- 运行应用并尝试三个不同的引擎。只需选择一个引擎并将其放置在地板或桌子上。以下图片显示了地板上的黄色引擎:

场景中显示引擎 2
- 要更改引擎,只需按下另一个按钮,当前模型将更改。您还可以找到另一个位置并点击它以使其出现:

引擎 3 出现在表面
在本节中,您已经学习了如何创建一个简单的界面来更改 AR 中出现的模型。有了这个,您现在有了进一步发展并构建更复杂应用的基本技能,以便您可以展示和操作自己的原型。
摘要
在本章中,我们介绍了如何使用 Google 的 ARCore 创建原型查看器应用程序来使用 AR。我们学习了如何集成 ARCore 和 Sceneform 库的功能,使生成 AR 场景的任务变得更容易,并且我们包含了我们自己的外部 3D 模型。我们还创建了一个基本的用户界面,使我们能够在不同模型之间切换。
现在,您已经拥有了使用 ARCore 创建自己应用程序的技能。您可以通过添加自己的原型或原型部件来改进当前项目,例如,当用户按下按钮时使模型分解成更小的部件,或者通过另一个按钮改变模型的颜色。这一章节为您探索在平坦表面上显示的 AR 可能性奠定了基础。
您还更了解 AR 在制造领域的应用,并且可以探索它提供的进一步可能性,而不仅仅是这里提供的示例。
在接下来的章节中,我们将探索其他 AR 工具和技术。其中一些将与 ARCore 相关,如 WebAR,而其他则完全不同,如 Augmented Class!、EasyAR 和 Vuforia。
进一步阅读
如果您想进一步探索本章中完成的项目,我们建议您探索以下选项:
-
AR 图像:您不必将物体放置在表面上,而是可以将它们附加到物理图像(图片、平面等)上。您可以在
developers.google.com/ar/develop/java/augmented-images/找到有关如何实现这一功能的起点。 -
使用 Sceneform 探索可用的示例,您只需下载并使用 Android Studio 打开它们:
developers.google.com/ar/develop/java/sceneform/samples。 -
在第二章,Unity AR 开发入门中,我们介绍了 Unity 3D。ARCore 可以在 Unity 平台内部使用,这也使得添加 3D 模型的过程变得更简单。它还接受更多的扩展。您可以在
developers.google.com/ar/develop/unity/quickstart-android找到有关如何开始的更多信息。
第四章:使用 WebAR 和增强类!进行 AR 培训
在本章中,我们将探讨两种适用于 Android 设备的工具,这些工具可以应用于培训领域。第一个工具将基于 WebAR,具体来说,是 Google Web 组件<model-viewer>,它将允许我们通过网页使用 ARCore 在真实环境中可视化 3D 模型。我们将能够在网页上从一系列模型中选择一个,将其放置在现实世界中,并对其进行操作(移动、旋转和缩放)。
第二个工具将是增强类!,这是一个以教育为导向的创建工具,它将允许我们创建 AR 培训项目,在图像或真实生活中的图片上展示不同的元素(图像、音频文件、视频和 3D 模型等),为我们的项目添加交互性,并在用户之间交换它们。
本章的主要目标是介绍两种 AR 工具,其应用场景与本书其他章节略有不同。本章的主要思想是让你发现与我们已覆盖或将要覆盖的其他 SDK 不同的 AR 形式,以及它们在如此跨领域的培训领域中的价值。到本章结束时,你将能够通过 Web 使用 ARCore 创建自己的 AR 查看器,但你也将发现使用增强类!工具丰富 AR 应用程序用户体验的交互性可能性。
在撰写本书时,这两个工具都在持续开发和改进中,不断添加新的功能和集成。目前,它们仅适用于 Android 设备,但预计它们很快也将支持 iOS。
在本章中,我们将涵盖以下主题:
-
使用 AR 进行培训
-
探索使用 Google 组件
<model-viewer>的 WebAR -
探索增强类!
技术要求
本章的技术要求如下。
对于<model-viewer>项目,你需要以下内容:
- 支持 ARCore 的 Android 设备(请参阅以下列表:
developers.google.com/ar/discover/supported-devices)。该项目已在 Pocophone F1 上进行了测试。
对于增强类!项目,你需要以下内容:
- 安装有 Android 5.0 或更高版本的 Android 设备
本章的资源和相关代码文件可以在这里找到:github.com/PacktPublishing/Enterprise-Augmented-Reality-Projects/tree/master/Chapter04。
使用 AR 进行培训
增强现实在教育领域已经存在了 20 多年,尤其是在大学范围内,尽管其增长速度比在更商业化的领域如市场营销或旅游要慢得多,也较少受到关注。
随着支持硬件(如手机、平板电脑和数字白板)的演变,AR 已经成为教育和培训中的一个宝贵资产。它允许学生通过图像或直接在房间内以三维形式可视化概念,以便他们能够更快、更动态地获取信息(只需用摄像头指向而不是在书本或互联网上搜索信息),或者创建更深入的个人项目(使一幅画栩栩如生,在手工项目上添加说明或额外信息,创建动画演示等)。
一个重要的考虑因素是,在教育/培训中,AR 技术适用于所有年龄段和学科:一个孩子可以在课堂上用它来学习形状和颜色,而一家公司可以用它来培训员工关于其职业风险预防计划——这完全取决于工具和 AR 内容的目标。
在本章中,我们将学习如何使用两种不同且易于使用的工具,这些工具将帮助我们快速创建两个不同的教育项目。为此,我们将使用以下 3D 模型:
-
sketchfab.com/3d-models/gearbox-planetary-2bee7992d266456aaef1f1394b0ebb98 -
sketchfab.com/3d-models/warm-gearbox-e7fedd86a90b4c46a53fe88882e66aa3 -
sketchfab.com/3d-models/gearbox-conical-60f023924ee0456daa758eb590b6064b
让我们从学习 Google Web Component <model-viewer>是什么以及它是如何工作的开始,来了解 WebAR。
使用 Google Web Component <model-viewer> 探索 WebAR
在智能手机进入市场之前,增强现实(AR)技术仅在计算机上开发。后来,出现了网络应用程序,最初是用 Flash 编写的,然后是 HTML5,但始终需要计算机的摄像头。自从 ARCore(谷歌)和 ARKit(苹果)工具包出现以来,AR 技术也通过网络进入了智能手机。
WebXR 设备 API 是当前正在努力提供从网络访问 VR 和 AR 的规范之一,包括使用设备的传感器或头戴式显示器(HMDs)。这个标准规范是由万维网联盟(W3C)编写的,目前正处于开发中。在撰写本文时,AR 在 WebXR 规范中的集成仍然不稳定,因此没有在本章中介绍。预计在接下来的几个月里,这一功能将得到进一步开发。有关标准和其进展的更多信息,您可以查看他们的网站(www.w3.org/TR/webxr)和 GitHub(github.com/immersive-web/webxr/)。
在本节中,为了开发 WebAR 应用程序,我们将使用 Google 的<model-viewer>网络组件,它允许我们轻松地将 3D 模型嵌入到网页中,并使用智能手机或平板电脑在 AR 中可视化它们。
Web 组件是一个基于现有网络标准的自定义 HTML 元素,它可以在现代浏览器中工作。
Google 的<model-viewer>组件首次于 2019 年 2 月推出,允许用户在网页中显示 3D 模型。2019 年 5 月,他们宣布通过ar属性实现 AR 兼容性。它基于 ARCore 功能场景查看器,目前仅适用于支持此技术的 Android 设备。我们将看到它的使用非常简单,并且可以在任何浏览器上工作。在第三章,“使用 ARCore 的 AR 制造”,我们学习了如何实现一个完整的 AR 移动项目。在这种情况下,我们只需使用提到的<model-viewer>组件来使用其网络功能。我们将看到我们可以使用哪种类型的模型,如何创建一个包含组件的网页,以及如何实际上添加组件并在移动设备上使其工作。
现在我们已经了解了我们将要使用的工具,在下一节中,我们将介绍此组件接受的 3D 模型(截至编写时)。
与 3D 模型一起工作
由于我们在浏览器中显示模型,支持的格式是GL 传输格式(glTF)2.0/glb,这是一种旨在最小化大小和运行时处理的格式,使其成为网络传输的最佳选择。如今,许多 3D 设计程序,如 Blender、3ds Max 和 Maya,以及一些 3D 模型平台,如 Sketchfab,都提供了导出此格式的工具。
你可以在www.khronos.org/gltf/和github.com/KhronosGroup/glTF/blob/master/README.md上找到有关 glTF 功能及其可能性的更多信息。
3D 模型的纹理可以是.jpg或.png格式,该工具支持动画,并且由于模型将通过网络浏览器显示,它们不应太重,以保持 AR 体验流畅。
更多关于这些要求的信息可以在developers.google.com/ar/develop/java/scene-viewer找到。
对于这个项目,我们将使用三个静态模型,分别是gearbox_conical.glb、gearbox_planetary.glb和gearbox_worm.glb。这些模型提供了良好的细节,以实现更真实的 AR 体验,我们将在下一节中使用增强类来使用它们!
现在我们已经了解了<model-viewer>组件的基本工作原理,让我们开始创建一个网页。
创建简单的网页
我们将要做的第一件事是创建一个网页,其中将显示 3D 模型,并准备好在 AR 中启动。为此,我们也将使用 Glitch,这是一个在线工具,将帮助我们创建此项目。
首先,我们将学习如何在编写样式表和 HTML 页面之前如何准备 Glitch 项目。
使用 Glitch 进行编码
Glitch 是一个用于创建具有强大协作组件的 Web 应用的简单工具。它允许我们混搭现有应用或从 GitHub 或 GitLab 等服务克隆项目。在我们的情况下,因为我们只想创建一个简单的演示网页,我们将使用 Glitch 来存储 HTML 页面和 3D 模型。要创建一个新的 Glitch 项目,请按照以下步骤操作:
-
首先,前往
glitch.com并点击登录按钮。它将自动创建一个账户。 -
在页面右上角,点击新建项目以开始新项目。然后,点击第一个选项,
hello-webpage:

选择我们的项目模板
- 你将被导向一个看起来类似的板:

Gitch 板
查看 README 文件,因为它解释了页面的主要功能。
- 下一步将是更改 Glitch 为我们提供的项目名称。点击页面左上角的名称并提供名称和描述:

修改项目的默认名称
- 现在,从下拉按钮“显示”中选择“紧邻代码”:

选择如何查看最终网页
- 这将把我们的窗口分割,以显示我们正在编写的代码的结果:

窗口显示左侧的代码和右侧的结果
- 让我们上传我们的模型。点击左侧栏上的资产,并将此项目的三个模型(即
gearbox_planetary.glb、gearbox_worm.glb和gearbox_conical.glb)拖放到方块上:

资产窗口
- 一旦模型已上传,它们将出现在仪表板上:

资产窗口中列出的资产
- 选择每个模型将允许你复制资产的链接或
删除它:

链接到资产和删除按钮
Glitch 保存我们按下的每个键,因此我们不需要手动保存代码。
在准备好基本元素后,让我们编写网页代码,从样式表开始,然后是 HTML 页面。
编写样式表
在样式表中,我们将决定我们网页的外观。由于我们的主要目标是展示 AR,所以我们现在会保持简单。Glitch 的style.css文件中已经有一些代码。让我们修改这个文件并适应我们的需求。按照以下步骤进行操作:
- 我们将保持
body括号不变:
body {
font-family: "Benton Sans", "Helvetica Neue", helvetica, arial, sans-serif;
margin: 2em;
}
在这里,我们指定了网页将使用的字体和body元素的边距。
- 接下来,我们将修改
h1标题元素:
h1 {
text-align: center;
color: #000000;
font-style: bold;
}
现在,标题将居中、黑色和粗体。
- 让我们添加一些类元素:
.box{
max-width: 600px;
margin: 4em auto;
border-radius: 8px;
box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.7);
text-align: center;
overflow: hidden;
}
这个类将封装在网页上显示的 3D 模型(不在 AR 中)。它们将出现在一个盒子里,带有圆角边框和柔和的阴影。我们将添加的文本将居中在盒子内,并且overflow: hidden参数将防止内容从盒子溢出。
- 现在,我们将为模型的 CC BY 信息添加另一个类,这对于这些类型的模型是必需的:
.cc{
display: flex;
justify-content: flex-start;
margin: 0.5em;
font-style: italic;
}
在这里,我们将内容定位在左侧,并使用斜体文本。
- 我们还将更改
cc类图像的外观:
.cc img{
height: 1em;
opacity: 0.6;
}
这两条线将选择这个类中图像的height并使它们略微透明。
- 最后,我们将修改
<model-viewer>组件的样式:
model-viewer {
width: 100%;
height: 580px;
}
通过这种方式,我们将使模型查看器占据容器盒子的width并设置其height。
现在样式表已经准备好了,我们可以创建我们的页面。
编码 index.html 页面
现在,打开index.html文件,在文档的开头将网页标题从Hello!改为AR Training Web App。你可以保留<head> <head>标签之间的其余代码不变。现在,删除<body> <body>标签之间的所有内容(如果你愿意,可以保留带有 Glitch 按钮的最后两行)。
现在,让我们在<body>标签内添加标题和三个模型盒子:
- 在
<h1>标签之间添加标题,使其使用我们的.css文件中的样式:
<h1>Select a gearbox to display in AR</h1>
- 现在,在标题之后,添加第一个带有顶部标题和底部 CC BY 信息的盒子:
<div class="box">
<h2>Planetary Gearbox</h2>
<div class="cc">
<a href="https://creativecommons.org/licenses/by/2.0/" target="_blank">
<img src="img/cc.svg">
<img src="img/by.svg">
</a>
<a href="https://sketchfab.com/3d-models/gearbox-planetary-2bee7992d266456aaef1f1394b0ebb98" target="_blank">T-FLEX CAD ST (Free)</a>
</div>
</div>
主要组件是box类。在里面,我们有<h2>格式的标题和带有指向许可证的cc类,以及两个来自creativecommons的图像来标识 CC BY 许可证类型,还有指向模型来源的 Sketchfab 页面的作者链接。
- 对其他两个模型也做同样的处理:
<div class="box">
<h2>Worm Gearbox</h2>
<div class="cc">
<a href="https://creativecommons.org/licenses/by/2.0/" target="_blank">
<img src="img/cc.svg">
<img src="img/by.svg">
</a>
<a href="https://sketchfab.com/3d-models/warm-gearbox-e7fedd86a90b4c46a53fe88882e66aa3" target="_blank">T-FLEX CAD ST (Free)</a>
</div>
</div>
<div class="box">
<h2>Conical Gearbox</h2>
<div class="cc">
<a href="https://creativecommons.org/licenses/by/2.0/" target="_blank">
<img src="img/cc.svg">
<img src="img/by.svg">
</a>
<a href="https://sketchfab.com/3d-models/gearbox-conical-60f023924ee0456daa758eb590b6064b" target="_blank">T-FLEX CAD ST (Free)</a>
</div>
</div>
目前,你的项目应该看起来像这样:

带有三个盒子的网页
现在,我们必须包含<model-viewer>组件的 3D 模型。
将组件添加到我们的页面
添加<model-viewer>组件相当简单。按照以下步骤进行操作:
- 首先,我们不得不在
<body>元素末尾添加以下两行:
<script type="module" src="img/model-viewer.js"></script>
<script nomodule src="img/model-viewer-legacy.js"></script>
通过这些行,我们将模块添加到我们的页面,并使其在新旧浏览器中工作。
如果您想使用模块的特定版本,请在 model-viewer 后的 URL 中添加版本号,例如:/model-viewer@0.3.1/.
- 然后,我们可以在
box类内部调用它,在h2标题之后和cc类之前,引用模型的 URL(在src属性中放入您自己的模型 URL):
<model-viewer src="img/6f8eb042-0e74-4182-9d39-4f877746edb1%2Fgerabox_planetary.glb?v=1566506940560" alt="Planetary Gearbox" background-color="#42697b" auto-rotate camera-controls ar></model-viewer>
以下截图显示了代码界面:

<model-viewer> 的最终代码
如您所见,<model-viewer> 标签支持多个属性:
-
src、background-color和alt属性分别定义了源 URL、背景颜色和描述。 -
auto-rotate属性将使模型在网页上默认旋转(平面视图,不是 AR 视图)。 -
使用
camera-controls,我们可以在模型处于平面视图时旋转/缩放模型。 -
对于我们来说,这里最重要的属性是
ar;没有它,查看模型在 AR 中的选项将不可用。
- 对其他两个模型做同样的操作:
...
<model-viewer src="img/6f8eb042-0e74-4182-9d39-4f877746edb1%2Fgearbox_worm.glb?v=1566506941410" alt="Worm Gearbox" background-color="#42697b" auto-rotate camera-controls ar></model-viewer>
...
<model-viewer src="img/6f8eb042-0e74-4182-9d39-4f877746edb1%2Fgearbox_conical.glb?v=1566506963689" alt="Conical Gearbox" background-color="#42697b" auto-rotate camera-controls ar></model-viewer>
- 这样,您应该会看到网页上加载并旋转的三个模型:

显示 3D 模型的网页
我们已经完成了编码。现在,让我们拿出我们的手机或平板电脑,查看 AR 中的模型。
在 AR 中可视化 3D 模型
要在 AR 中查看模型,您需要使用支持 ARCore 的设备打开网页。一旦您有了这样的设备,可视化模型的步骤如下:
-
通过点击 Glitch 网页左上角的分享按钮并选择 Live App 来获取您最终页面的 URL。
-
现在,复制 URL 并将其粘贴到您的移动设备上。您应该看到 3D 模型正在加载(由于它们是详细的模型,可能需要比在电脑上更多的时间):

显示在手机上的网页
-
在每个模型的右下角,您会看到一个在电脑浏览器中不会出现的方块。点击它。
-
第一次这样做时,会出现一条消息,询问页面是否可以打开 Google Play 服务 AR,如果您还没有安装,它会要求您安装它:

Google Play 商店中的 AR Google Play 服务
- 现在,您将看到全屏的 3D 模型,底部有一个按钮可以查看您的空间中的 AR 版本。点击它以启动相机并将其指向一个平坦的表面:

全屏显示的模型,下面有按钮可以查看 AR 版本
- 一旦模型被固定到表面上,我们就可以在它周围移动。通过触摸屏幕,您可以移动、旋转和缩放它:

在真实地板上方的 AR 模型
- 现在,您可以调整模型的大小和位置,从不同的角度查看它,并在其中移动。
重要!3D 模型必须通过 HTTPS 连接访问。否则,当点击右下角的小方块时,模型中的“在您的空间中查看”按钮将不会出现。如果您在未来应用程序中使用自己的服务器而不是 Glitch,请记住这一点。
就这样。现在,您知道了如何使用 Web 组件<model-viewer>和 ARCore 在 AR 中显示模型。
如我们之前提到的,组件相当新,并且一直在不断变化。要查看最新功能和接受属性,您可以查看googlewebcomponents.github.io/model-viewer/和github.com/GoogleWebComponents/model-viewer。
在下一节中,我们将使用相同的 3D 模型创建另一个培训项目,但使用 Augmented Class!工具。我们将使用图像标记并向我们的最终项目添加交互。
探索 Augmented Class!
Augmented Class!是一个由一群开发者和教师/教授的动机产生的教育内容创作工具,它提供了一个完整的解决方案,允许教育社区的全体成员(教师、学生和家长)无需技术知识,无需这些工具通常的约束(如内容有限和功能有限),创建和共享交互式 AR 项目。
目前,在 3.0.30 版本中,它可以在 Google Play Store 中免费获取,并且为 PC 提供私人测试版。该应用程序使用图像标记,在其他工具中称为目标。这意味着它会在真实图像上显示虚拟内容,例如图片、书封面等,而不是像 ARCore 那样在平坦表面上显示。Augmented Class!允许广泛的内容(图像、音频文件、视频、3D 模型和文本),我们还可以添加交互(触摸屏幕、与相机和标记之间的距离互动,以及两个标记之间的距离互动),并在用户之间共享我们的项目。在这个版本中它是免费的,预计他们将在接下来的几个月内推出更多免费和专业的功能。更多信息,请访问www.augmentedclass.com。
在这一章中,我们将使用 Android 应用程序创建一个简单的项目来显示变速箱的 3D 模型。然后,我们将添加用户交互以显示更多信息。最后,我们将创建另一个标记并在它们之间创建交互。为此,我们将在移动设备上准备我们的材料(图像和 3D 模型),创建一个简单的项目,向其中添加一些用户交互,并创建两个不同标记之间的交互。
要做到这一点,我们需要为我们的移动设备准备所有材料。
准备材料
在开始项目之前,我们必须在我们的移动设备上准备材料,以便我们可以快速访问它:
-
我们首先需要做的是在他们网页上注册([
creativitic.es/augmentedclass/beta/](http://creativitic.es/augmentedclass/beta/))并下载 Android 应用(https://play.google.com/store/apps/details?id=com.AugmentedClass.AClass&hl=es_419)。该应用允许我们进行演示访问,而无需登录,但对于项目来说,它比注册访问有更多的限制。 -
现在,在您的手机或平板电脑上,在
root文件夹中创建一个名为AClass的文件夹,并将模型文件gearbox_worm.glb以及标记gearbox_worm.jpg和component_desc.jpg复制到其中。创建文件夹不是必需的,但它会使使用和搜索应用中的内容更容易。
现在,我们已经准备好开始使用应用了。
创建一个简单项目
我们将首先创建一个简单项目,看看如何使用基于图像的标记在培训项目中使用 AR。让我们开始吧:
- 打开应用,授予所需的权限,并在登录页面输入您之前提供的电子邮件地址收到的用户名和密码:

Augmented Class! 应用登录窗口
- 第一次打开应用时,您将需要完成一个简单的教程,其中您需要遵循一些基本步骤来使用一些给定资源创建一个非常简单的项目:

初始教程
-
完成教程后,从主菜单中,按“进入发明者”。
-
在发明者窗口中,点击创建的新项目以选择它,然后通过按删除图标来删除它:

创建了项目并删除了教程的发明者窗口
-
现在,点击创建新项目以进入黑板窗口。
-
在做任何事情之前,给项目命名,这样您以后就可以识别它了。
-
在这里,我们可以选择我们的标记类型。它们如下所示:
-
简单标记:在所选图像上显示 AR 内容
-
摄像头交互:当摄像头远离标记时显示一些 AR 内容,当摄像头靠近标记时显示另一种不同的 AR 内容
-
标记交互:当标记分离时在每个标记上显示 AR 内容,当它们靠近时在每个标记上显示其他内容
选择 简单标记:

从顶部栏给项目命名
- 我们首先需要做的是选择一个标记。我们可以选择一个之前的标记,用我们的相机拍摄一个图像,或者上传一个标记。将“加载标记”的方形拖动到中间的白色方形上,并从您的移动设备中选择
gearbox_worm.jpg图像:

将“加载标记”方形从左侧滚动视图拖动到中间
- 现在,我们可以将我们的 3D 模型添加到标记中。点击左侧的 3D 按钮,并将“加载模型”拖到屏幕中间的标记上:

将“加载模型”方块拖到中间的标记上
- 导航到我们之前创建的
AClass文件夹并选择gearbox_worm.glb。如你所见,接受许多文件类型:

选择我们的 3D 模型
- 等待模型加载完毕。你会看到模型默认被选中,并且顶部栏上显示着新的按钮。选择手形图标来操纵模型。使用移动/旋转/缩放按钮,操纵齿轮箱,直到它看起来如下:

3D 模型旋转并缩小
多手势选项允许你用更少的按钮来操纵模型。
- 现在,在层次结构面板下按场景保存图标。我们的当前标记将被保存,并在底部栏上出现缩略图:

当前标记作为缩略图出现在底部栏
- 在左上角点击“项目”按钮退出黑板。然后,从左上角点击“主页”按钮进入主菜单。在那里,按“转到查看器”。在这里,我们可以看到我们的项目在网格上:

带有我们项目的查看者窗口
- 由于我们只有一个项目并且它已经被选中,请按眼睛图标来加载 AR。然后,用摄像头指向标记,以在图像上看到 3D 模型出现。移动和旋转图像,靠近或远离它,从所有角度查看模型:

齿轮箱出现在图像标记上
发明者和查看者窗口都有一个打印按钮,这样你就可以在没有它们的情况下打印带有标记的 PDF。
就这样。我们已经准备好了基本项目。现在,让我们给它添加一些交互功能。
添加用户交互
让我们通过让用户触摸屏幕来添加一些交互性,这样他们就可以在悬停在标记上时查看更多的 AR 信息。按照以下步骤操作:
- 返回到发明者窗口并选择我们的项目。按铅笔图标来编辑它:

编辑一个项目
- 按下缩略图然后按铅笔图标来编辑标记的场景:

选择和编辑场景
- 让我们添加一些信息。在左侧栏中,按文本按钮并将其中一个字体拖到标记上:

将文本元素拖到标记上
- 输入文本
Worm gear,并使用操作按钮将其移动到金色齿轮(蜗轮齿轮)旁边我们的 3D 模型:

将文本定位在它所引用的对象旁边
- 为了更容易放置,你可以通过按相机图标然后按带有眼睛的相机来更改相机视角:

将相机视图切换到俯视图
- 现在,选择文本后,按时钟图标以添加交互并选择手形图标。这样,当模型可见时,用户触摸屏幕,文本将出现:

选择文本的交互
你可以通过按它们或在层次结构面板中按它们的名称来选择场景中的不同元素。
- 保存场景并返回到观众窗口以启动 AR。现在,当模型出现在图像上时,按它。文本将出现:

当触摸屏幕上的元素时出现的文本
在本节中,我们学习了如何为我们的标记添加基本交互。在下一节中,我们将创建一个标记交互。
在标记之间创建交互
现在,我们将创建一个标记交互。我们将有两个标记:模型,如前几节所述,以及一些简单的文本,“组件描述”。
在本例中,我们将保持简单,当我们用相机聚焦于模型的标记时,它将显示 3D 模型。然而,当我们把两个标记放在一起时,描述文本将出现。
因为我们将重用我们的 3D 模型的标记,我们将创建另一个项目。在一个项目中,单个标记不能重复,因为观众不知道它应该在标记上显示哪个内容。因此,我们将启动一个新的项目并创建必要的交互。让我们开始吧:
- 在项目窗口中创建一个新的项目,在黑板窗口中将其命名为
交互式变速箱。对于此项目,选择两个标记交互:

带有两个标记的新项目
如你所见,右上角将出现一个新的按钮:分离/一起。此按钮将在两种模式之间切换(当标记分离和在一起时),允许我们在每种情况下在标记上放置不同的内容。
- 现在,从标记列表中,将
gearbox_worm作为第一个标记:

将之前上传的 gearbox_womr1 图像拖动到第一个标记上
- 现在,将加载标记方框拖动到第二个标记上以加载
component_desc.png图片:

拖动负载标记方框从移动设备加载图像
- 按下 3D 按钮,并将
gearbox_worm模型从滚动视图的末端拖动并放到第一个标记上。这将是我们标记分离时的内容:

拖动之前上传的模型
- 现在,点击“一起”按钮,切换到我们将它们放在一起时将出现的内容。你会看到之前的内容将从场景中消失:

场景变为“一起”模式
-
重复步骤 4,将模型放置在第一个标记上方。
-
选择文本按钮,并将其中一个字体拖放到第一个标记的两个单独实例中,以创建两组不同的文本。选择并放置如下:

包含模型和信息文本的场景
- 你可以利用相机的按钮来缩小场景,从顶部查看,以便正确放置文本:

改变相机视图后的相同场景
- 就这样。现在,按保存按钮并返回到查看器窗口以启动 AR。在网格中选择当前项目并按眼睛图标:

选择在 AR 中显示的当前项目
- 现在,你会看到,当它们分离时,变速箱显示 3D 模型:

当标记分离时,只显示模型
- 现在,当它们放在一起时,我们展示了之前添加的 3D 模型和文本:

当标记与模型结合并显示信息时
除此之外,这种交互对于复杂的解释非常有用,例如化学反应(当它们分离时,不同的成分以某种方式表现,当它们在一起时以另一种方式表现),对于构词,对于指令(我们可以有如组件描述、组装或基本维护等标记,并且根据我们将哪个标记靠近模型,将显示不同的信息),等等。
分享项目
在设备上创建的所有项目都存储在本地。然而,你可能希望与你的学生或同事分享其中之一或多个。为此,请按照以下步骤操作:
-
前往项目窗口。
-
选择项目并按分享图标:

分享所选项目
- 对于多选,长按项目直到出现复选框,然后选择你想要的任意多个:

分享多个项目
- 将打开一个窗口,你可以通过电子邮件、社交媒体等方式分享你的项目文件:

选择如何分享项目(们)
要导入另一个人的项目(或你在另一台设备上创建的项目),请按照以下步骤操作:
-
从你的电子邮件或驱动器下载项目文件,或你分享它的地方(记住你下载它的文件夹):
-
前往项目窗口。
-
点击下载图标(当未选择项目时唯一的激活图标):
-

选择导入项目文件
- 浏览到下载文件的文件夹并选择它:

选择项目文件
项目(s)将自动导入。
一旦新的项目被导入到你的项目窗口中,你可以像编辑和删除其他任何你创建的项目一样编辑和删除它们。
接下来是什么?
到目前为止,你已经学会了如何创建一个简单的标记和两个标记交互,并为触摸屏添加了交互功能。为此,我们使用了 3D 模型和一些文本,但你也可以尝试用视频文件或音频解释来丰富当前的项目。
另一方面,增强类!提供了更多选项,包括与摄像头的交互(当摄像头远离标记时内容改变,当摄像头靠近标记时内容改变),延迟显示内容(元素在一段时间后出现,它们可以再次消失或不消失),以及内容编辑(视频和音频循环,文本颜色和样式等)。一旦你尝试了所有这些选项并且熟悉了它们,就可以设计并创建一个使用所有可能交互的完全交互式项目。
摘要
在本章中,你学习了两种不同的训练项目工具。第一个是基于 ARCore 的 Web 功能,它允许我们无需编写太多代码,就可以将 AR 可视化添加到任何在网页上显示的 3D 模型。第二个工具增强类!使我们能够轻松创建可以服务于不同目的的交互式教育项目,例如学习某个作品的基础知识,培训维护工程师等。
现在,你对 AR 的通用性有了更好的理解,它可以在移动设备和 Web 应用程序上使用,以及交互如何帮助创建更深入和更有价值的体验。凭借你在本章中获得的技术,你可以尝试将你的项目迁移到其他领域和需求,以及进一步探索这两个工具,以便你可以改进当前的项目。
在下一章中,我们将开始使用 Unity 3D 环境和一些可以集成到其中的其他 AR 工具。在这里,你将学习如何使用 EasyAR 工具的图像识别过程来创建一个 AR 目录。
第五章:使用 EasyAR 进行 AR 营销
本章将向您介绍 EasyAR,这是一个易于使用且直观的 AR SDK,具有多种功能,可以单独使用,也可以像本章中那样集成到 Unity 3D 中。您将学习基于图像的 AR 是什么以及它是如何通过使用您自己的图像作为标记符与 EasyAR 一起工作的。您还将学习如何将自定义 3D 模型导入 Unity,以便通过图像标记符使用 AR 显示它。最后,您将创建一个增强型目录,您的家具将在此目录中栩栩如生。
本章有两个主要目标:学习 EasyAR 及其功能,并了解 AR 作为营销工具的可能性。如今,EasyAR 与 Vuforia 一样,是最多才多艺的 AR SDK 之一,可用于多种用途。在本章结束时,您将具备基本技能,以继续改进当前项目或通过探索 EasyAR 提供的其他功能来创建新的和改进的项目。正如您将看到的,AR 是一种非常强大的营销工具,可用于多种目的,例如影响用户、以更视觉和吸引人的方式展示产品,以及提供与 AR 体验集成的折扣和奖品。本章的目的是,到本章结束时,您将了解该领域 AR 的基本用法,以便之后可以探索其可能性。
重要!在本章中,我们将使用 Unity 3D,因此如果您还没有这样做,我们建议您首先阅读第二章,Unity AR 开发入门,以便熟悉其布局、命名约定和功能。
在本章中,我们将涵盖以下主题:
-
使用 AR 进行营销
-
理解 EasyAR
-
构建基于图像的 AR
-
使用自定义 3D 模型
-
创建 AR 目录
技术要求
本章的技术要求如下:
-
支持 Unity 3D 的计算机(请在此处查看最新要求:
unity3d.com/es/unity/system-requirements)。本章的示例项目是在 Windows 10 x 64 计算机上开发的。 -
Unity 3D(本书中为 2019.1.2f1)。
-
Microsoft Visual Studio Community 2017(包含在 Unity 安装中)。
-
EasyAR SDK(本书中为 3.0.1)。
-
搭载 Android 4.2 或更高版本或 iOS 8.0 或更高版本的移动设备(EasyAR 要求:
www.easyar.com/doc/EasyAR%20SDK/Getting%20Started/3.0/Platform-Requirements.html)。项目已在三星 Galaxy A5(2017)和 Pocophone F1 上进行过测试。
本章的资源和相关代码文件可以在此处找到:github.com/PacktPublishing/Enterprise-Augmented-Reality-Projects/tree/master/Chapter05.
本章中的项目已经使用 Windows 10 PC、三星 Galaxy A5(2017)和 Pocophone F1 安卓设备进行了测试。对于 iOS 开发,你还需要使用苹果电脑进行开发,因为 Unity 将构建一个 Xcode 项目。
使用增强现实进行市场营销
增强现实技术最初出现时,市场营销领域是它最先涉足的领域之一。这项技术的视觉冲击力使其对潜在客户极具吸引力,它可以从产生“哇”效果到解释产品的特性。
当增强现实技术刚开始时,它主要用于影响用户。一种接近全息术概念的新技术,让我们能够看到自己和他人被虚拟元素和角色所包围,这是一个很好的诱惑。大品牌开始在购物中心使用它,人们可以在大屏幕上看到自己和虚拟动物、恐龙或著名角色的形象。随着移动设备的普及,增强现实市场营销技术已经发生了变化:用户现在负责体验,可以与之互动。品牌现在可以超越“哇”效果,创造功能性体验来推广和销售他们的产品。这包括增强目录,在平面的图像上显示 3D 产品,虚拟镜子,你可以通过它购买在增强现实中所试戴的眼镜,以及能够解释制造过程中元素的包装等等。
增强现实在市场营销中取得成功的主要理念是它必须具有意义和吸引力,以确保用户会想要下载应用程序并使用它,并且在体验之后,他们会记住你的品牌,会回到你这里,或者会从你这里购买。
在本章中,我们将使用增强现实(AR)技术来创建一个家具目录,椅子将从其页面中栩栩如生地呈现出来。我们还将为用户提供更改这些椅子颜色的可能性。
当专注于使用移动设备查看目录页面时,我们希望我们的潜在客户能够从所有角度看到产品,以便他们能够更好地了解他们正在购买的产品,并对其产生更强的情感联系。在实时中定制产品的某些方面,如颜色,可以帮助激发对其的兴趣。
对于我们的项目,我们将使用来自欧洲座椅公司([www.euroseating.com/en/](https://www.euroseating.com/en/))的真实目录页面和 3D 模型,该公司在全球 100 多个国家设有业务。使用他们的高质量 3D 模型和真实目录将帮助我们把这个项目可视化,使其成为一个可以在任何其他市场营销环境中使用的真实生活增强现实应用。
本章中将使用的模型和图像已由该公司发布,用于本书的上下文。
在我们开始这个项目之前,让我们快速了解一下 EasyAR 是什么以及如何将其集成到 Unity 中。
理解 EasyAR
EasyAR 是一个支持 Android、iOS、UWP、Windows、Mac 和 Unity 编辑器的多平台增强现实 SDK。一个 AR 引擎使我们能够以简单的方式创建 AR 解决方案,并提供多种 AR 功能,包括以下内容:
-
平面图像跟踪:一种识别和跟踪现实世界中先前选定的图像的位置、旋转和缩放的技术,例如书封面、照片或名片。
-
表面跟踪(SLAM):一种检测表面并跟踪其中对象的技术。
-
3D 对象跟踪:一种定位和跟踪真实 3D 对象的位置和方向的技术,而不是平面图像。
-
屏幕录制:一个功能,允许我们在播放 AR 场景时录制视频。
EasyAR 的一些主要功能如下:
-
它具有直观的目标管理界面,因此可以在运行时生成目标,而无需我们从其网站上上传或下载任何内容,例如其他工具。
-
它支持本地和云端识别。
-
它支持不同目标和相同目标的多目标跟踪。
-
它支持 3D 跟踪,在真实环境中检测和跟踪具有丰富纹理的 3D 对象。
EasyAR 有一个基于 Web 的平台,用户可以通过它注册他们的项目并获得他们测试和发布应用程序所需的许可证。EasyAR SDK 有两种不同类型的版本:
-
EasyAR SDK Basic 免费用于商业用途,没有任何限制或水印。它基于图像目标提供 AR 能力,可以加载和识别多达 1,000 个离线目标,并支持多目标跟踪、表面识别、透明和流式视频播放以及二维码识别。我们需要明确指出,该应用程序是用 EasyAR 开发的。
-
EasyAR SDK Pro 包括 Basic 版的所有功能,以及 3D 对象跟踪、多类型目标检测和屏幕录制。Pro 版的价格为每个许可证密钥$499.00,但提供有限使用的免费试用版(每天最多 100 次)。功能比较、定价和付款详情列在 EasyAR SDK 产品页面https://www.easyar.com/view/sdk.html上。
对于我们的项目,基本许可证的功能就足够了。让我们开始使用 EasyAR 吧。
在我们开始使用 EasyAR SDK 之前,我们需要将其集成到 Unity 中(查看第二章[54a1260e-a741-4eb5-9c98-01350fcba94b.xhtml],Unity AR 开发简介,为 Unity 准备系统部分,了解如何首次安装和使用 Unity)。
为了下载并将 EasyAR SDK 导入 Unity,请按照以下步骤操作:
-
通过访问 EasyAR 的网页
www.easyar.com/view/signUp.html创建账户。您需要接受开发者协议才能创建账户。 -
创建账户后,您将收到一封确认邮件,以便您激活并登录。
-
登录后,转到 EasyAR 下载页面(
www.easyar.com/view/download.html),在右侧列的 Unity Packages 部分,选择 EasyARSense_3.0.1-final_Basic_Unity.zip 进行下载。此包包含引擎和不同用途的基本示例。解压以获取.unitypackage文件。 -
现在,我们可以创建 Unity 项目。打开 Unity Hub,从顶部栏点击新建:

打开 Unity Hub 创建新项目
- 给项目命名并指定位置,然后点击创建:

为项目命名和指定位置
-
项目创建完成后,将 EasyAR 包导入 Unity。为此,解压压缩文件后,您可以直接双击生成的
.unitypackage文件(最快的方式),或者从 Unity 内部,您可以通过点击 Assets|Import Package|Custom Package...并选择.unitypackage文件来完成。 -
新窗口将显示 EasyAR 包内的所有文件。点击导入:

将 EasyAR SDK 导入 Unity
- 正如您将看到的,四个新文件夹将出现在您的项目窗口中:EasyAR 和 Plugins,它们包括构建不同平台 EasyAR 所需的主要资源和代码,以及 Samples 和 StreamingAssets,它们包含示例资源和代码:

项目中已添加四个新文件夹
到目前为止,我们有一个包含 EasyAR 引擎和示例的新项目。在下一节中,我们将学习如何使用它来构建一个检测真实图像并在其上显示虚拟立方体的应用。
构建基于图像的 AR
您可以使用不同的技术构建 AR;最常见的一种是基于图像的 AR,它包括跟踪之前选定的图像(目标)并在其上叠加虚拟内容,同时考虑图像的位置、旋转和大小。这种跟踪需要使用不同的算法,这些算法通过设计的特征点区分图像,并将图像在相机流中定位到三维空间。别担心——EasyAR 会为您完成这项工作。您需要做的只是决定哪些图像将作为目标,以及哪些虚拟内容将叠加在其上。
为了创建这个项目,我们将使用 EasyAR 的 ImageTarget 示例项目作为参考,因为它已经包含了我们应用所需的所有组件。但在开始 AR 元素之前,我们将设置我们的项目文件夹:
- 我们将要做的第一件事是创建我们的个人
资产文件夹,@MyAssets,以区分我们导入到 Unity 中的其他资产。在这里,我们将添加所有外部资源,例如标记图像和 3D 模型。为此,在项目窗口上右键单击并选择创建|文件夹。将其命名为@MyAssets:

在主 Assets 文件夹下创建一个新的文件夹,并命名为@MyAssets
- 在此内部创建三个其他文件夹,分别命名为
Images、Models和Scripts:

包含三个文件夹的@MyAssets 文件夹
注意:此项目目前在Assets文件夹下有六个文件夹。正如你所见,项目往往会迅速增长,在我们意识到之前,我们的资源就迷失在文件夹和文件的混乱之中。花几分钟时间为我们的项目文件夹创建一个基本结构总是一个好的做法。
- 现在,我们可以创建我们的 AR 场景。正如我们之前提到的,我们将使用 EasyAR 的示例场景作为参考。为此,从项目窗口中,双击位于 Assets|Samples|Scenes 的 HelloAR_ImageTarget 场景以打开它:

HelloAR_ImageTarget 示例场景
这里,我们有我们复制自己的 AR 项目所需的所有元素。
- 现在,点击 File|Save As...并将场景保存到 Assets|Scenes 文件夹中,命名为
ARScene:

以另一个名称保存场景
通过这样做,我们已经创建了示例场景的副本。如果我们的场景发生任何问题,我们总是可以回到原始版本。
现在我们有了初始场景,我们可以查看每个组件并根据我们的需求进行定制。
理解我们的 AR 场景
一个 AR 场景有两个主要组件,这些组件是任何基于图像的 AR SDK 共有的:
-
AR 相机:将接收来自相机设备的输入并处理这些帧以搜索所选图像(目标)的相机对象。
-
图像目标:我们将虚拟元素放置其上的真实图像的表示。当相机在真实世界中找到此图像目标时,它将显示附加到其上的虚拟元素。
在 EasyAR 中,我们有三个主要元素(除了方向光之外):
-
主相机,它是将渲染来自我们移动设备的图像的元素。
-
EasyAR_Setup,它负责应用的主要操作,例如初始化和操作 EasyAR 引擎,将物理相机设备附加到场景中的主相机元素,或通过 ImageTracker 实现图像目标检测和跟踪:

EasyAR_Setup 元素及其元素
- ImageTarget,这是我们想要识别的图片的表示。它包含在真实世界中检测到或丢失时出现的虚拟元素。在这种情况下,ImageTarget 已经包含两个子项:一个 Quad,代表我们将要追踪的图片,和一个 Cube,我们将用它来最初测试场景。要识别的图片的值在 Image Target Controller 的检查器窗口中显示,如下面的截图所示:

带有子项在左侧和组件值在右侧的 ImageTarget
Image Target Controller 中的参数如下:
-
目标名称:目标的名称。这不必是图片的名称。
-
目标路径:这是我们想要用作目标的图片的完整路径。它与
类型选项直接相关。 -
目标大小:目标的大小。我们通常会将其设置为
1。 -
类型:目标图片是否存储在项目的资源中(具体来说,是我们在项目窗口中已有的
StreamingAssets文件夹)或者目标路径是否为绝对路径。 -
图像追踪器:这是将在相机流中搜索此 ImageTarget 的 ImageTracker。
-
目标类型:在这里,我们将使用第一个选项,本地图片,因为我们的图片将包含在项目内部。
现在我们已经看到了场景的主要元素,接下来我们需要做的是创建我们自己的目标。
准备目标
让我们创建我们的目标。我们首先需要将必要的图片和资源添加到我们的项目中。按照以下步骤进行操作:
- 将位于
Images文件夹中的Target_Maia.jpg图片从项目资源拖到StreamingAssets文件夹,并将Target_Maia_texture.jpg图片拖到我们的@MyAssets/Images文件夹,如下面的截图所示:

分别在各自文件夹中的Target_Maia.jpg和Target_Maia_texture.jpg图片
第一张图片将是我们的目标。我们将使用第二张图片,它比第一张小,来在编辑器中指导目标的大小。
我们不能重复使用StreamingAssets文件夹中的图片,因为该文件夹中的文件不会被 Unity 编辑器处理,因此不能像常规文件一样直接在场景中使用。
- 在层次结构窗口中,选择 ImageTarget 并在检查器窗口中更改名称和路径值,如下面的截图所示:

Image Target 行为参数
使用这些参数,我们告诉 ImageTracker 在项目的流媒体资源中寻找名为Target_Maia.jpg的目标。
注意:您可以使用StreamingAssets文件夹内的文件夹来组织您的目标。在这种情况下,您需要将文件夹添加到目标路径属性中(例如,MyFolder/Target_Maia.jpg)。
- ImageTarget 没有与之关联的图片,这意味着我们实际上在编辑器中看不到它。为了可视化我们的目标将看起来如何,特别是为了看到虚拟内容将如何覆盖真实图像(大小、位置),我们将使用 ImageTarget 的子对象中已有的四边形元素。在项目结束时,当我们不再需要它时,我们将删除这个四边形元素。将
@MyAssets/Images/Target_Maia_texture图片从项目窗口拖到四边形上,使其成为其纹理:

将 Target_Maia_texture 拖动到四边形
- 现在,我们必须调整四边形的纵横比,使其与我们的图像的纵横比相匹配。我们将通过将 Y 缩放设置为
0.7来实现这一点,如下面的截图所示:

四边形的变换组件及其值
我们的场景已经准备好了。我们有了主相机、EasyAR_Setup,我们的 ImageTarget 中包含了我们要识别的图片的路径,以及四边形和立方体 作为子对象,这样当标记被识别时它们就会显示出来。接下来我们需要做的是获取 EasyAR 密钥来测试场景。
获取密钥
要测试当前场景,我们需要将密钥添加到 EasyAR GameObject 中。这个密钥由 EasyAR 生成以许可应用程序:
-
前往 EasyAR 开发中心(
www.easyar.com/view/developCenter.html#license),如果你还没有登录,请登录,然后点击添加 SDK 许可证密钥。 -
在那里,选择 EasyAR SDK Basic,并填写以下详细信息:
-
应用程序名称:
AR Catalogue -
包标识符(iOS):
com.banana.arcatalogue(如果你打算在 iOS 上构建你的应用程序,则需要填写此信息) -
包名(Android):
com.banana.arcatalogue(如果你打算在 Android 上构建你的应用程序,则需要填写此信息)
这些名称对应于 Unity 中的应用程序名称和包(com.companyname.productname)。
如果你将来想要更改这些名称,你将必须确保在密钥生成面板中更改它们,并将生成的密钥复制/粘贴回 Unity 中。
- 在面板中选择创建的密钥,并将 SDK 许可证密钥(适用于 EasyAR SDK 3.x)复制到位于 Assets|EasyAR|Common|Resources 的 Easy AR Key 元素中:

EasyARKey 设置脚本
一旦我们有了密钥,我们就可以测试场景了。
测试场景
现在,让我们测试场景:按Ctrl + S 保存所有内容,确保你的电脑连接了摄像头,然后在工具栏顶部点击播放按钮。系统应该会自动启动摄像头。如果你指向标记(无论是打印的还是显示在屏幕上的),你应该在游戏视图中看到背景中的四边形和从它弹出的立方体:
要以全屏模式查看场景,你可以在按下播放按钮之前,在游戏视图的右上角点击最大化。

游戏窗口最大化,显示在目标上出现的立方体
再次点击播放按钮以停止模拟。
重要! 请记住,在模拟模式下,要停止模拟或对场景所做的任何更改,点击播放按钮后都不会被保存。
故障排除
如果你看不到 AR 场景,你可以转到“控制台”选项卡(它在底部栏或“游戏”视图旁边的标签上)并查看那里的信息。
如果一切正常,它应该只显示信息消息,即 EasyAR 成功初始化、其版本等信息。然而,如果出现 404 未找到的错误消息,这意味着目标没有正确设置。请检查所有步骤,特别是 ImageTarget 中的 Path 参数,确保它指向正确的文件。在以下屏幕截图中,目标名称是Target_Maia2.jpg而不是Target_Maia.jpg:

显示常见信息消息和错误的控制台
在任何情况下,你都可以尝试在 Unity 论坛(forum.unity.com/)或 EasyAR 论坛(forum-test.easyar.com/)中调试错误。
测试场景的这一步不是必需的,尽管强烈推荐。将应用构建到设备上需要时间,因此建议先测试它,确保它按预期工作。
现在,让我们构建这个应用。
构建应用
要构建新的安卓应用,有一些步骤你始终必须遵循:
-
你需要做的第一件事是选择平台。为此,点击文件|构建设置。
-
点击“添加打开场景”将我们的当前场景添加到(空)将要构建到应用中的场景列表中。
-
在“平台”下,选择 Android 并点击“切换平台”。等待 Unity 为所选平台重新编译资源:

包含当前场景和已选择 Android 平台的“构建设置”窗口
- 然后,点击“玩家设置...”以配置应用设置。在弹出的窗口中,我们暂时会更改一些设置:
-
公司名称:
Banana -
产品名称:
AR 目录
这些名称与我们用于生成 EasyAR 密钥代码时使用的名称相同。
以下图像显示了包含新添加的公司名称和产品名称字段的“项目设置”窗口:

在项目设置中填写公司和产品名称
- 然后,在“其他设置|识别”中,设置以下内容:
-
包名:
com.banana.arcatalogue(确保它与 EasyAR 密钥生成中的名称匹配,否则应用在初始化时会报错,说包名不匹配密钥) -
版本:
1.0 -
最小 API 级别:
Android 5.0 'Lollipop' (API level 21) -
目标 API 级别:
自动(最高已安装):
根据 EasyAR 的文档,SDK 与 Android 4.2 及以上版本兼容,但出于性能原因,并且为了在用户设备上获得流畅的 AR 体验,我们建议将最低 API 级别设置为 5.0。

其他设置选项卡内的识别部分
- 如果您在 Unity 外部安装了 Android SDK,在打开 Player Settings 之前,Unity 很可能告诉您它找到了 Android SDK,并询问您是否想使用它。如果是这种情况,请点击 是:

如果我们已经安装了 SDK,则使用已安装的 SDK
- 关闭 Player Settings 窗口,使用 USB 线缆将您的移动设备连接到计算机,并确保您的设备已激活 USB 调试,以便可以直接从 Unity 将应用程序部署到其中。要激活此选项,一般步骤如下:
-
通过转到设置|关于设备启用开发者模式。
-
然后,连续点击七次构建号,直到出现一个通知,表明开发者选项可用。
-
前往开发者选项并激活 USB 调试,以允许计算机安装并启动应用程序。
重要! 如我们之前提到的,这些步骤是通用的。如果您有任何疑问,请尝试找到您设备的特定情况,因为选项的名称可能因制造商而异。
-
现在,在 Build Settings 窗口中点击 Build And Run,将您的 APK 命名为
arcatalogue.apk,然后点击保存。Unity 将立即开始编译,寻找 Android SDK (如果它没有检测到,它将要求您选择其安装的文件夹)* 并搜索合适的设备(如果设备没有正确连接或未激活 USB 调试,它将告诉您找不到设备)。然后,它将开始构建过程,直到将 APK 复制到设备并启动它。 -
一旦应用启动,将摄像头指向目标,以便看到立方体:

移动设备上目标上的立方体截图
如果由于任何原因,您不想/不能将 APK 建立到移动设备中,您可以使用 Build 而不是 Build And Run 来创建 APK 而不安装它。
当编译过程完成后,您将需要手动将生成的 APK 复制到您的设备并安装它。
注意:此过程仅适用于 Android 设备。要在 iOS 设备上编译应用程序,您必须从 Apple 计算机上构建和运行 Unity 项目,当构建过程完成后,它将自动启动 Xcode,构建过程将在其中结束(您将需要分配您的 Apple ID 才能在 iOS 设备上播放应用程序,就像您需要使用任何其他在 Xcode 中开发的 iOS 应用程序一样)。
在本节中,你学习了如何使用 EasyAR 检测图像并在其上显示虚拟立方体。现在,我们将用我们将导入到项目中的外部 3D 模型替换测试立方体。
使用自定义 3D 模型
在上一节中,我们学习了如何使用 EasyAR 创建一个简单的 AR 应用来显示立方体。在本节中,我们将将自己的 3D 模型导入到 Unity 中,以便在目标上可视化并玩弄其材质和纹理。
对于这个项目,我们将使用fbx,这是一种允许我们包含材质、纹理和动画的导出格式。要查看 Unity 接受的所有导出和本地 3D 格式的列表,请访问docs.unity3d.com/Manual/3D-formats.html。
在将模型包含到我们的项目中之前,我们将对我们的场景进行一些修改以改进它:
- 在“层次”窗口中选择“方向光”。然后,在检查器窗口中,将阴影类型设置为无阴影。阴影非常消耗资源,在这种情况下,AR 体验将受益于没有阴影:

检查器窗口中的方向光属性
- 现在,选择“ImageTarget”并更改其变换值,使其在 x 轴上旋转。这样,在场景中,物体将看起来是从地面弹出的:

ImageTarget 变换值
- 最后,选择“主相机”并旋转和移动它,使其指向目标:

主相机变换值
现在,是时候包含 3D 模型了。让我们开始吧:
- 在“层次”窗口中,通过右键单击“Cube”并选择“删除”,或者直接选择它并按键盘上的Delete键来从“ImageTarget”中删除“Cube”:

删除“Cube”模型
-
将提供的代码资源中的
Models/Maia文件夹拖动到项目窗口中的@MyAssets/Models。这将导入.fbx网格对象及其位于textures文件夹中的纹理文件,如下面的截图所示。 -
将
maia.fbx文件拖动到“ImageTarget”中。请记住确保它在“ImageTarget”内部,这样它就会在目标出现/消失时出现/消失。移动、旋转和缩放模型,直到它在目标上看起来很好:

目标内的“maia”模型
- 现在,点击工具栏顶部的播放按钮来测试当前场景。当目标被检测到时,座椅将出现:

当目标被检测到时,座椅出现
- 再次点击播放按钮停止模拟,然后保存场景(Ctrl + S)。将移动设备连接到计算机,按 Ctrl + B,或者转到文件|构建设置|构建并运行,以将应用程序构建到设备中。
现在我们已经有了基本 AR 场景,在下一节中,我们将通过添加另一把椅子和创建 UI 来允许用户与我们的家具进行交互来创建我们的 AR 目录。
创建 AR 目录
现在我们已经创建了基本场景,我们将创建一个小的 AR 目录:
-
我们将使用两个 ImageTargets 来展示两把不同的椅子。
-
我们将允许用户在查看椅子时更改椅子的颜色。
修改 AR 场景
在本节中,我们将通过添加一个新的 ImageTarget 来修改当前的 AR 场景。为此,我们将遵循与上一节相同的步骤:
-
从项目资源中,将
Target_Prince.jpg图像拖到Assets/StreamingAssets文件夹中。 -
然后,将
Target_Prince_texture.jpg图像拖到Assets/@MyAssets/Images文件夹中:

Target_Prince 和 Target_Prince_texture 在各自的文件夹中
- 然后,将包含模型的
Prince文件夹拖到Assets/@MyAssets/Models中:

王子模型
- 右键单击 ImageTarget 并选择复制,这样我们就可以将其用作新 ImageTarget 的模板:

复制 ImageTarget
-
将第一个 ImageTarget 重命名为
ImageTargetMaia,当前的一个重命名为ImageTargetPrince,以便您可以区分它们。将它们在场景中移动,以便它们不会重叠。 -
将以下目标名称和路径参数复制到检查器窗口中的 ImageTargetPrince 的图像目标控制器中:

图像目标控制器参数
-
将
Target_Prince_texture.jpg图像从Assets/@MyAssets/Images文件夹拖到项目窗口中的 Hierarchy 窗口的 ImageTargetPrince 的 Quad 上,以便将其作为纹理应用。 -
从 ImageTargetPrince 中删除 maia 模型(右键点击并删除)并将王子模型拖到那里。
-
将王子模型移动、旋转和缩放,直到它在标记的中间位置,看起来很合适。
以下截图显示了我们的场景,其中包含两个 ImageTargets 及其相应的座位:

包含两个目标和模型的场景
- 在测试我们的场景之前,让我们隐藏 Quad 对象,这样它们就不会出现在 AR 中,我们只能看到椅子。为此,选择两个 Quad 游戏对象(使用Ctrl + 左键点击进行多选)并取消选中它们的 Mesh Renderer 组件:

隐藏 Quad 游戏对象
-
现在,按播放键以测试一切设置是否正确。用摄像头指向一个目标,然后指向另一个目标,以查看椅子。
-
再次按播放键以停止模拟并继续进行更改。
-
目前,EasyAR_Setup GameObject 的 ImageTracker 已被设置为一次只检测一个标记。让我们将此值增加到
2,以便我们的用户可以一起看到两张椅子:

改变同时目标数量
现在,测试一下——你应该会看到两张椅子同时出现。
下一步,我们需要创建一个脚本,允许用户更改座椅的纹理。
创建控制器脚本
在本节中,我们将创建一个脚本,该脚本将控制场景并允许我们的用户更改座椅的纹理。让我们开始吧:
- 在@MyAssets|Scripts 中,通过右键单击并选择创建|新 C#脚本创建一个新的 C#脚本。命名为
MainController,然后双击它以在 Visual Studio 中打开:

在@MyAssets/Scripts 文件夹中创建一个新的 C#脚本
- 如果你按照第二章中介绍的步骤安装 Unity,即《AR 开发入门》,你将已经安装并配置了 Visual Studio,并且它将以默认代码打开脚本,如下面的截图所示:

Visual Studio 中的 MainController 脚本
- 如果你是在安装 Unity 之前安装了 Visual Studio 或者使用了其他程序如 MonoDevelop,你可以通过点击编辑|首选项|外部工具|外部脚本编辑器来配置 Unity 使用它打开脚本,如下面的截图所示:

将 Visual Studio 分配为外部脚本编辑器的首选项窗口
- 在脚本中,首先在类声明之后添加以下行:
public class MainController : MonoBehaviour
{
public Material[] materials;
public Texture2D[] textures;
...
在这里,我们正在声明materials数组,这是我们存储两张椅子材质的地方。我们将用它来改变这些材质的纹理属性。textures数组将包含我们将应用到这些材质的实际图像(红色和蓝色)。这两个变量都是公开的,因为我们将从 Unity 编辑器初始化它们。
- 在
Start()方法内部,添加以下循环:
foreach (Material material in materials)
{
material.mainTexture = textures[0];
}
通过这个循环,我们将materials数组中的每个材质分配给textures数组中的第一张图像。
- 在
Update()方法之后,我们将创建一个新的方法:
public void ChangeColor()
{
foreach (Material material in materials)
{
if (material.mainTexture == textures[0])
material.mainTexture = textures[1];
else
material.mainTexture = textures[0];
}
}
此方法更改椅子的材质纹理(红色或蓝色)。它检查哪个纹理被选中,并将另一个分配给两张椅子。
- 现在,回到 Unity 编辑器,将脚本拖到 EasyAR_Setup GameObject 上,以便脚本影响当前场景。
记住,只有当脚本附加到场景中的一个 GameObject(或多个)时,它才会被执行。否则,它只存在于项目窗口中,但不在实际场景中。
由于此脚本没有直接引用它附加到的元素,它可以应用于场景中始终处于活动状态的任何元素(因此它始终可用)。我们将其放在 EasyAR_Setup 中,因为它是一个满足此规则的根元素。
- 展开脚本的两个变量,即材质和纹理,然后在材质中设置大小为
2并选择 tela 和材质#5。这些是每个模型中对应布料的材质:

分配材质到变量
- 在纹理中,将大小设置为
2并选择红色和蓝色元素,即 Acapulco 3011 和 Acapulco PANTONE 2935 C:

将纹理分配给变量
控制器脚本已准备就绪。现在,我们必须创建用户界面和按钮,该按钮将通过我们刚刚创建的ChangeColor()方法触发颜色变化。
创建界面
让我们创建一个简单的界面,以便我们的用户可以更改他们看到的 AR 对象的特性。让我们开始吧:
- 首先,在层次结构窗口中右键单击并选择 UI|Canvas。Canvas 元素是 Unity 界面上的主要元素,包含所有其他元素:

在场景中创建 Canvas 元素
-
默认情况下,画布位于(0,0)点,朝后,覆盖整个 3D 场景,并且具有当前屏幕大小。在层次结构窗口中双击其名称,以便场景聚焦于它。
-
在检查器窗口中,为 Canvas Scaler 包含以下值:
-
UI 缩放模式:按屏幕大小缩放。使用此参数,我们正在告诉画布根据不同的屏幕大小进行适应(在为不同移动设备编译时很有用)。
-
对于参考分辨率,我们将使用
1280x720。 -
屏幕匹配模式允许我们根据屏幕的宽度和/或高度调整 UI 元素。值为
0.5表示它将适应两者:

检查器窗口中的 Canvas Scaler 值
要操纵 UI 元素(移动、缩放等),在工具栏中选择它们的特定工具:

- 我们将使用一个图标作为我们的颜色按钮。为此,将
circle_icon.png图像导入到Assets/@MyAssets/Images。在项目窗口中选择它。然后,在检查器窗口中,修改其纹理类型,使其为 Sprite(2D 和 UI),以便在 UI 中使用。然后按应用以保存此更改:

将 circle_icon 转换为精灵图像
- 现在,在层次结构窗口中右键单击 Canvas 并选择 UI/Button:

在 Canvas 元素内创建按钮
- 我们不需要按钮附带的自带文本组件,因此右键单击它并删除它:

删除按钮的文本组件
- 将按钮的名称更改为
Color_button并将其之前导入到其 Image 组件中的图标分配给 Source Image。点击 Preserve Aspect 复选框以确保它始终是圆形的:

在检查器窗口中的 Color_button 图像组件
- 现在,让我们将按钮放置在屏幕的右上角。对于 Rect Transform 组件,点击正方形并选择右上角选项以移动按钮的锚点:

为按钮选择右上角锚点
- 然后,将 PosX、PosY、Width 和 Height 值更改为调整按钮的位置和大小,如下所示:

按钮的新 Rect Transform 值
- 现在,在按钮被选中后,在检查器窗口的 Button 组件下,转到
On Click ()方法并按 + 符号创建一个新动作:

在 On Click() 方法中创建一个新动作
- 从层次结构窗口中将 EasyAR_Setup 元素拖动到 None (Object) 框中,然后从右侧的下拉菜单中选择 MainController|ChangeColor。通过这样做,我们告诉 UI,每当 Color_button 被按下时,附加到 EasyAR_Setup GameObject 的
MainController类的ChangeColor()方法将被执行:

为 Color_button 选择 ChangeColor() 方法
-
播放场景以测试它。你会看到当你点击 Color_button 时,椅子的纹理会改变。然而,还有一个小的细节:按钮不够直观,因为它不会改变自己的颜色。为了解决这个问题,我们将在 Visual Studio 中的代码中添加几行。
-
返回 Visual Studio 并在
MainController脚本中在文件开头导入UnityEngineUI库:
using UnityEngine.UI;
- 在
Start()方法之前添加以下变量:
public Image color_button;
private Color32 red = new Color32(159, 40, 40, 255);
private Color32 blue = new Color32(40, 74, 159, 255);
我们将使用第一个来分配 Unity 编辑器中的按钮(这就是为什么它是 public 的),以及两个颜色作为参考。
- 在
Start()方法中的循环段之后添加以下行以初始化按钮为红色:
color_button.color = red;
- 在
ChangeColor()方法内添加以下行:
if (color_button.color == red)
color_button.color = blue;
else
color_button.color = red;
在这里,我们告诉按钮评估当前颜色,如果它是 红色,则将其更改为 蓝色,反之亦然。这样,按钮的颜色将与座椅的纹理同时改变。
- 最后,在 Unity 编辑器中,将 Color_button GameObject 拖动到
EasyAR_SetupGameObject 上的 Color_button 变量以分配它:

将 Color_button GameObject 拖动到主控制器的最后一个变量
-
在编辑器中保存并测试场景,以查看按钮最初如何改变颜色以及每次按下时如何改变颜色。
-
现在,在你的移动设备上构建并运行该应用,享受看到座位在 AR 中如何生动起来的过程:

手机截图显示两个座位都是红色
你可以围绕座位移动相机,靠近它们,或将目标移动以查看它们的细节。你可以按颜色按钮来切换它们的纹理颜色。现在应用已经完成,你甚至可以删除场景中的四边形平面,因为它们不再需要。有了这个,你的项目就准备好了。
摘要
在本章中,你学习了如何使用 EasyAR SDK 创建 AR 目录。你学习了如何将 SDK 导入 Unity 并创建一个显示在 ImageTarget 上的场景。然后,你学习了如何从 Unity 外部导入模型并修改它们的一些功能,例如材质和纹理。然后,你将模型合并到初始场景中,使目录中的座位栩栩如生。最后,你添加了一个脚本和 UI 元素来控制模型的颜色。
到本章结束时,你已经掌握了使用 EasyAR 继续开发的基本技能,并尝试了其一些其他功能。为此,我们建议打开位于“资产 | 示例 | 场景”的其余样本场景并尝试它们,以了解它们是如何工作的。你还了解了如何使用 AR 创建用于营销的目录、杂志或类似产品。你现在可以改进这个项目,例如,将产品与电子商务链接起来,为消费者提供完整的体验并吸引他们购买你的产品。你现在可以使用基本工具来创建自己的 AR 营销体验。
在下一章中,你将学习如何使用另一个 SDK,Vuforia,将相同的座位模型放置在真实环境中,而不是使用 ImageTargets。你将学习如何使用 Vuforia 的地面平面功能在平坦的表面上放置和操作 3D 模型,例如在桌子上或地面上,以创建一个交互式零售体验。
第六章:使用 Vuforia 的 AR 零售
在本章中,你将使用 Vuforia,这是最著名的 AR SDK 之一,它提供了广泛的选择(包括与图像目标一起使用和不使用图像目标、网络和本地识别等),以及可以直接下载和测试的示例。它还具备集成到 Unity 编辑器的优势,这使得使用它进行开发更加容易。
本章的第一个主要目标是向你介绍 Vuforia SDK 及其工作原理。在其众多功能中,你将学习如何使用空间识别和增强现实将 3D 对象放置在现实世界中,而无需预先打印的图像目标。你将学习如何使用 Vuforia 融合技术与 ARCore 结合或不结合使用,并掌握在 Unity 中使用 Vuforia 元素的能力。本章的第二个目标是向你展示 AR 在零售中的吸引人应用,展示潜在客户如何在自己的空间中查看家具、画作、装饰品等产品。通过这类应用,他们可以决定想要购买哪些元素,以及它们在自己家中将如何呈现,使他们更多地参与到购买过程中。
在本章中,我们将涵盖以下主题:
-
使用 AR 进行零售
-
探索 Vuforia
-
移动中的 AR – 使用地面平面
-
创建 AR 家具查看器
技术要求
本章的技术要求如下:
-
一台支持 Unity 3D 的计算机(请参阅最新的要求:
unity3d.com/unity/system-requirements)。本章的示例项目是在 Windows 10 x 64 计算机上开发的。 -
Unity 3D(本书中为 2019.1.2f1 版)。
-
Microsoft Visual Studio Community 2017(包含在 Unity 安装中)。
-
Unity 3D 中包含的最新版本的 Vuforia(本书中为 8.3.8 版)。
-
一款支持 Vuforia Fusion 的移动设备(请参阅
library.vuforia.com/content/vuforia-library/en/articles/Solution/ground-plane-supported-devices.html)。
本章的资源和相关代码文件可以在以下位置找到:github.com/PacktPublishing/Enterprise-Augmented-Reality-Projects/tree/master/Chapter06。
使用 AR 进行零售
零售是 AR 提供更广泛可能性之一的领域,从满足和吸引消费者以减少退货产品,到将产品与社交媒体链接或个性化购物体验。以下是一些例子:
-
在购买之前尝试产品。这是用户在真正购买产品之前可视化衣服、鞋子、眼镜甚至化妆品的地方。
-
通过 AR 看看家具、艺术品或甚至墙面涂料在家中的样子。
-
在商店,在购买之前查看有关产品的额外信息,例如评论和评价。
-
在购物中心,接收来自其中商店的地理位置信息和折扣。
-
在超市或大型商店中,通过区域引导客户到他们想要的产品。
这个领域还允许我们在各种硬件上显示 AR,包括客户的移动设备、触觉屏幕和虚拟试衣间。因此,在过去的几年里,零售业的 AR 解决方案数量激增,尤其是在 ARKit(来自苹果)和 ARCore(来自谷歌)进入市场之后。这两款软件使我们能够利用移动设备的摄像头和传感器轻松识别环境,并在地面或桌子等平坦表面上放置虚拟元素。
在本章中,我们将利用 Vuforia Fusion,Vuforia SDK 的地形检测功能,该功能还可以与 ARCore 结合使用,在我们的周围环境中放置虚拟对象,而无需任何类型的打印目标,创建一个客户可以用来查看家具如何融入他们家庭的 AR 家具查看器。
对于我们的项目,我们将使用来自 Euro Seating 公司的真实目录页面和 3D 模型,该公司在全球 100 多个国家设有业务。www.euroseating.com/en/,一个座椅制造商。使用他们的高质量 3D 模型和真实目录将帮助我们把这个项目可视化为一个真实的 AR 应用,可以在任何其他营销环境中使用。本章中使用的模型和图像已由该公司转让,用于本书的上下文中。
我们将首先探索 Vuforia 以及如何将其集成到我们的 Unity 项目中。
探索 Vuforia
Vuforia 最初由高通公司开发,目前由 PTC 运营,是历史最悠久且最知名的 AR SDK 之一。它是市场上最稳定和性能最好的软件之一,与 ARKit 和 ARCore 一起,是 AR 开发者的首选之一。
Vuforia 提供了一系列功能,包括 2D 图像和 3D 对象跟踪、无需参考图像即可启动 AR 内容的无标记 AR(本章我们将使用)以及类似条形码的标记称为 Vumarks。它提供了多个示例和额外功能,如虚拟按钮、运行时图像目标创建和背景视频纹理操作。
与其他 AR 软件一样,Vuforia 需要在移动设备上部署时需要许可证。Vuforia 提供免费的开发密钥生成器,当应用处于生产阶段时,必须将其切换为部署密钥。您可以在他们的网页上查看其定价选项:developer.vuforia.com/pricing。
Vuforia SDK 可以下载用于 Android 和 iOS,并且也可以在 Unity 3D 平台上使用。自 Unity 2017.2 版本以来,它直接集成到 Unity 编辑器中,就像任何其他主要资源一样,并且必须在其中安装和激活。现在,我们将 Vuforia 集成到一个新项目中,并设置它以便可以在 Android 设备上构建。让我们开始吧:
- 当您第一次在计算机上安装 Unity 时(见 第二章,Unity AR 开发入门),您应该选择了添加 Vuforia 模块选项。如果您没有安装它或者您不确定,请打开 Unity Hub,转到 安装 标签页,并检查您 Unity 版本底部的已安装模块:

当前带有 Vuforia 支持的 Unity 安装
- 如果 Vuforia 不在那里,点击右上角的按钮,然后点击 Add Modules。选择 Vuforia 并安装它:

使用 Unity Hub 向当前 Unity 安装添加新模块
Vuforia 通常包含在稳定版本中;如果您正在尝试测试版或非常新的 Unity 版本,那么 Vuforia 可能不会出现在选项中,您可能需要安装一个旧版本才能使用它。
- 现在,打开 Unity Hub。在 项目 标签页上,点击 NEW:

在 Unity Hub 中创建一个新项目
- 填写 项目名称 和 位置字段,然后点击 CREATE:

创建一个新的 3D 项目
- 点击 Ctrl + N 或转到 文件|新建场景。现在,按 Ctrl + S 或转到 文件|保存。将文件命名为
OnTheGo并将其保存在场景文件夹中:

为当前项目创建一个新场景
- 您还可以从 项目窗口中删除项目附带的项目 SampleScene:

SampleScene 不再需要
- AR 需要一个特殊的相机,该相机检索物理相机流并将其处理,以便我们可以将虚拟元素集成到真实图像流中。Vuforia 提供了一个名为 AR Camera 的资源,它可以为我们完成这项工作。删除现有的 Unity 主相机,在 Hierarchy 窗口中右键单击,并选择 Vuforia Engine|AR Camera:

将 AR Camera 添加到场景中
- 由于这是我们第一次在项目中使用 Vuforia,会出现一个消息提示我们导入 Vuforia 的资源。点击导入:

导入 Vuforia 及其资源到项目的消息
在 项目窗口的 Assets 文件夹内,将出现一个名为 Vuforia 的新文件夹。
-
将方向光放置在 AR Camera 内部,以便光线随着相机移动。
-
现在,我们必须在 Player Settings 中启用 Vuforia,以便我们可以在场景中使用它:

Vuforia 行为组件检测到 Vuforia 尚未启用
-
按 Ctrl + Shift + B 或转到文件|构建设置...以打开构建设置窗口。
-
在进行任何其他操作之前,点击“添加打开的场景”以将我们的场景包含在构建场景列表中。
-
然后,通过点击 Android 并在右下角按下“切换平台”来切换平台。通过这种方式,我们将配置我们的项目,使其可以在 Android 设备上构建:

构建设置面板,允许我们添加新场景、切换平台和访问玩家设置
-
现在,点击“玩家设置...”以打开一个新窗口。
-
填写公司名称和产品名称(当我们将应用程序安装到设备上时应用程序将拥有的名称)。
-
在最后一个选项卡“XR 设置”中,启用“Vuforia 增强现实支持”以允许在此项目中使用 Vuforia:

已填写公司名称和产品名称并激活 XR 设置中的 Vuforia 的玩家设置
- 将会显示一条新消息,指出 Vulkan 图形 API 不支持 XR。要修复此问题,请打开“其他设置”选项卡并从图形 API 中删除 Vulkan:

在“其他设置|渲染”下从图形 API 中删除 Vulkan
- 在此之下,填写识别部分的“包名”和“最低 API 级别”:

在“其他设置|识别”下更新包名和最低 API 级别
目前,Vuforia 支持 Android 4.4 及以上版本和 iOS 11 及以上版本。然而,我们建议将最低 API 级别设置为 5,以确保运行应用程序的设备足够强大。您可以在以下位置检查 Vuforia 的最低要求:library.vuforia.com/articles/Solution/Vuforia-Supported-Versions。
- 此步骤并非总是必需,但可能的情况是,与您的 Unity 版本一起安装的 Vuforia 版本不是最新版本。如果是这样,当选择 ARCamera 时,Vuforia 行为组件上将会出现一条消息,指出有新版本可用:

在 ARCamera 的 Vuforia 行为组件中链接到新的 Vuforia 版本
- 点击链接下载可执行文件,并按照步骤进行安装:

Vuforia AR 设置向导
- 在更新 Vuforia 时,请确保您将其安装在 Unity 根目录中,通常在
C:/Program Files/Unity/Hub/Editor/{unity_version_name},并在需要时关闭当前运行的 Unity 会话。如果出现要求您更新项目的消息,请点击“更新”。现在,Vuforia 将在您的项目中是最新的:

来自 Vuforia 引擎的更新消息
现在我们已经知道了如何将 Vuforia 集成到新项目中,我们将开始使用其地面平面功能来创建一个检测平坦表面并在其上放置 3D 内容的应用。
行走中的 AR – 使用地面平面
Vuforia 的主要功能,用于在用户的环境中实时放置虚拟对象,被称为地面平面.* 我们将使用此功能创建一个应用,将 3D 内容放置在现实世界的水平表面上,例如地板和桌子。
从 Vuforia 7 开始,SDK 引入了一种新功能,称为Vuforia 融合,以提高空间识别的性能,这取决于每个设备的特性,包括摄像头、传感器、芯片组和内部 AR 框架。Vuforia 融合试图检测集成框架,如 ARKit(iOS)或 ARCore(Android),它们提供最佳性能。如果没有找到,它将尝试使用 VISLAM 和 SLAM。
同时定位与建图(SLAM)算法同时估计对象的位置和周围环境的地图。视觉惯性同时定位与建图(VISLAM)是 Vuforia 的算法,它将视觉里程计(VIO)和 SLAM 结合起来以提高后者的性能。
尽管列表迅速增加,但并非所有设备都支持 Vuforia 的地面平面。一般来说,如果运行设备支持 ARCore 或 ARKit,它将工作。如果不支持,它将取决于内部 AR 启用技术。Vuforia 在其网页上保留了一份当前支持的设备列表:library.vuforia.com/articles/Solution/vuforia-fusion-supported-devices.html。
在下一个子节中,我们将学习如何在 Vuforia 中启用 ARCore。如果你的设备不支持 ARCore,你可以直接跳到下一个子节。如果你计划将你的应用分发到支持和不支持 ARCore 的设备上,并且想要首先测试 Vuforia 的 VISLAM 性能,请跳过此步骤,在测试最终应用后进行此操作以查看差异。
在 Vuforia 中启用 ARCore
在本节中,我们将学习如何为 Vuforia 启用 ARCore;如果你的设备支持 ARCore,你将受益于与 Vuforia 一起使用它,因为生成的应用将更快、更精确地检测平坦表面。要在 Unity 中为 Vuforia 启用 ARCore,请按照以下步骤操作:
- 从 Google 的存储库下载 ARCore 库的最新版本。全局链接是
https://dl.google.com/dl/android/maven2/com/google/ar/core/<ARCORE_VERSION>/core-<ARCORE_VERSION>.aar。您可以在github.com/google-ar/arcore-unity-sdk/releases检查可用的最新版本。
在撰写此章节时,当前版本是 1.9.0,因此链接将是 dl.google.com/dl/android/maven2/com/google/ar/core/1.9.0/core-1.9.0.aar。
- 在 Unity 中,在项目窗口中,右键点击
Assets文件夹并按 Create|Folder。将其命名为Plugins并在它里面创建另一个名为Android的文件夹:

在 Assets 中创建一个新的文件夹
- 将下载的
.aar文件复制到Android文件夹内:

位于 Android 文件夹内的 ARCore 插件
- 选择文件,并验证在检查器窗口中是否已选中“选择平台以用于插件”下的 Android:

ARCore 库在检查器窗口中的属性
- 选择 ARCamera 并点击打开 Vuforia Engine 配置按钮:

从 ARCamera 打开 Vuforia Engine 配置
- 在设备跟踪器下,根据目标用户设备设置 ARCore Requirement 为 Optional 或 Required:

将 ARCore 设置为“可选”或“必需”
如果设置为“可选”,当使用地面平面时,Vuforia 将尝试使用 ARCore,如果设备不支持,它将切换到 Vuforia 的内部算法。如果设置为“必需”,则不支持 ARCore 的设备上的应用将无法工作。
现在我们已经配置了 ARCore,我们将创建一个 AR 场景来测试地面平面功能。
创建地面平面场景
本项目中的 AR 场景将包含以下元素:
-
ARCamera,它将检索物理摄像头的视频流并处理每一帧
-
地面平面查找器,负责搜索水平表面并在用户点击屏幕时将对象放置在其上
-
地面平面舞台,这是虚拟元素将要放置的父 GameObject
-
一个测试立方体,当用户点击屏幕时将出现在地面上
当我们在 Unity 中集成 Vuforia 时创建了 ARCamera 元素,所以让我们创建其余的元素以使地面平面功能正常工作:
- 右键点击层次窗口并选择 Vuforia Engine|Ground Plane|Ground Plane Stage。这将为我们想要在 AR 中显示的内容创建父 GameObject。它用一个 100 厘米方形的视觉参考来帮助虚拟对象的现实世界比例。这个参考仅在 Unity 编辑器内可见:

创建地面平面舞台元素
- 地面平面舞台 GameObject 上有两个脚本附加到它:
-
锚点行为,它决定了虚拟对象是附着在地面上还是在空中
-
默认可追踪事件处理器,这是 Vuforia 的默认脚本,用于在目标被找到/丢失时显示/隐藏元素
- 要创建一个虚拟对象进行测试,右键单击地面平面阶段并创建 3D Object|Cube。确保它作为地面平面阶段的子级出现,以便在适当的时候显示/隐藏:

创建一个立方体作为地面平面阶段的子级
- 缩小立方体,使其小于地面平面阶段的视觉参考。确保它在游戏视图中从 ARCamera 可见(如果不是,移动/旋转 ARCamera 或更理想的是地面平面阶段,直到它在视图中):

放置在地面平面阶段参考网格上的立方体
- 在层次结构窗口外部右键单击,并选择 Vuforia Engine|地面平面|平面查找器:

创建平面查找器以检测地面平面
- 此 GameObject 附有三个脚本:
-
锚点输入监听器行为,负责监听用户的输入(屏幕上的点击)
-
平面查找器行为,用于查找水平表面放置内容
-
内容定位行为,用于定位真实世界的内容
- 在内容定位行为脚本中,选择(或从层次结构拖动)地面平面阶段位于锚点阶段选择框内:

将地面平面阶段链接到平面查找器
- 在继续之前,按Ctrl + S 保存当前场景。
现在我们已经配置了 AR 场景,我们将添加 Vuforia 密钥,这是在移动设备上构建 Vuforia 所必需的步骤。
获取密钥
Vuforia 要求应用在真实设备上运行时需要一个开发/部署密钥。为此,请按照以下步骤操作:
-
前往 Vuforia 的开发者页面(
developer.vuforia.com/license-manager),注册并登录。 -
在许可证管理器选项卡上,选择获取开发密钥以获取开发期间使用的免费密钥。
-
给它起一个你应用的名字,
AR On the Go,阅读并接受条款和条件,然后按确认。 -
选择你新创建的许可证并复制密钥数字。
-
返回 Unity 编辑器并选择场景中的 ARCamera。
-
在检查器窗口中单击打开 Vuforia Engine 配置以打开通用 Vuforia 配置:

检查器窗口中的 ARCamera GameObject
- 在此处,将你的密钥粘贴到应用许可证密钥字段中:

检查器窗口中的 Vuforia 配置选项
现在,我们已经在项目中包含了一个 Vuforia 开发密钥,这将使我们能够在真实设备上构建和安装我们的应用。
请记住,当你想要将应用程序上传到商店(Google 或 Apple)时,你必须根据 Vuforia 的计划购买一个部署密钥。你可以在developer.vuforia.com/pricing找到更新的价格。
在下一节中,我们将测试我们的应用程序在 Unity 中,以确保一切按预期工作。
测试应用程序
在 Unity 中开发项目时,在构建之前测试它是良好的实践,因为构建过程需要时间。这样,你可以检测基本问题和错误,并在实际尝试在手机上运行应用程序之前快速纠正它们。
Vuforia 目前不能作为一个独立的应用程序构建,但它有一个与 ARCamera 集成的脚本,用于测试目的。当你正在 Unity 编辑器中测试应用程序时,它将使用电脑的摄像头来模拟 AR。如果它没有检测到摄像头,它将使背景保持黑色并直接播放 AR。
另一方面,当你使用地面平面项目并想要测试应用程序时,Vuforia 无法使用设备的传感器来检测平坦的表面。相反,它提供了一个图像目标参考来模拟地面平面识别,当相机检测到该图像时,它将表现得像在手机上检测到一个平坦的表面。
要测试我们的应用程序,请按照以下步骤操作:
-
在项目窗口中找到名为“
Emulator Ground Plane.pdf”的 PDF 文件,位于 Vuforia|Databases|ForPrint|Emulator。打印它并将其放置在地面上(你也可以直接在电脑上打开 PDF 图像,尽管尺寸参考可能不准确)。 -
在顶部的工具栏中按下播放按钮,并将网络摄像头指向图像。当软件检测到表面(在这种情况下为目标)时,你会看到一个视觉标记。在按下播放按钮之前,你可以点击游戏视图右上角的“播放时最大化”按钮,以便在屏幕上最大化显示图像:

游戏视图检测地面平面模拟器图像
- 点击游戏视图上的电脑屏幕以在手机上模拟屏幕触摸。立方体将出现在目标上方。其大小将取决于你在 Unity 编辑器中之前给出的尺寸(Unity 中的地面平面舞台为 100 厘米 x 100 厘米,而打印的模拟器为 20 厘米 x 20 厘米):

点击游戏视图时,立方体出现在地板上
如果一切按预期工作,我们可以更改立方体并开始塑造我们的 AR 应用程序,以在现实世界中显示家具。
创建 AR 家具查看器
现在我们有了 AR 场景的主结构,我们将定制应用程序以创建一个 AR 家具查看器,允许我们在现实世界中放置椅子。应用程序将让我们做以下事情:
-
在地面上放置一把椅子
-
复制椅子以创建类似电影院的场景
-
旋转椅子以调整其与环境的匹配
让我们开始吧!
向我们的项目中添加元素
我们将首先向我们的项目和场景添加新元素,包括 3D 模型和用户界面:
- 在项目窗口的
Assets文件夹中创建自己的文件夹,并将其命名为@MyAssets。然后,在它内部创建三个其他文件夹,分别命名为Images、Models和Scripts:

@MyAssets 内部的新文件夹
-
现在,从项目的资源中,将模型和图像复制到项目窗口中相应的文件夹。
-
在检查器窗口中,将
chair.png和cinema.png图像的纹理类型更改为精灵(2D 和 UI),然后点击应用。这将允许我们稍后将其用作 UI 元素。其他图像将作为常规纹理应用于平面上:

检查器窗口中的 chair.png 图像导入设置
-
将从 Assets|Models|Prince 文件夹中的王子模型拖动到层次结构窗口,作为地面平面舞台的子对象。
-
删除立方体,因为我们不再需要它了。
-
缩放它,旋转它,并移动它,直到它面向前方,在地面平面舞台上的合适大小(您可以在测试应用程序时稍后调整此大小):

场景中王子模型作为地面平面舞台对象的子对象
- 要创建 UI,在层次结构窗口中右键单击并选择 UI|按钮。它将自动将按钮封装在新的 Canvas 元素中,并将必要的 Event System 添加到场景中:

在层次结构窗口中创建按钮
- 选择画布,并更改 Canvas Scaler 的参数,以便它根据设备的屏幕大小进行缩放:

新的画布缩放器参数以适应 UI 的大小到屏幕大小
-
选择按钮并删除其 Text GameObject。
-
在检查器窗口中,将其名称更改为
chair_b以进行识别,并使用 Rect Transform 组件来设置其位置和大小。将椅子图像添加到图像组件的源图像中:

自定义创建的按钮
这是切换单个椅子移动和添加多个椅子以形成电影院的按钮:

游戏视图中椅子和按钮的视图
现在,我们必须创建一个包含应用程序逻辑的脚本。
添加应用程序的逻辑
现在,让我们通过向项目中添加新脚本来创建应用程序的逻辑。这将负责在单个和多个椅子之间切换:
- 在项目窗口的@MyAssets|Scripts 文件夹中,右键单击并选择创建|C#脚本。将其命名为
OnTheGoHandler.cs:

在项目窗口中添加新脚本
- 双击它以在 Visual Studio 中打开:

Visual Studio 中的 OnTheGoHandler 脚本
- 在脚本顶部添加
Vuforia库以使用其功能:
using Vuforia;
- 在类中声明以下变量:
public GameObject chairButton;
public Sprite[] buttonSprites;
private ContentPositioningBehaviour contentPosBehaviour;
private bool multipleChairs = false;
chairButton 变量将对应我们在 Unity 中创建的按钮。buttonSprites 数组将包含按钮的两个背景图像,我们将在这两者之间切换。contentPosBehaviour 变量来自 Vuforia 类,负责将我们的虚拟对象添加到现实世界中。我们将使用 multipleChairs 布尔值在两种状态(一把椅子或多把椅子)之间切换。公共变量将在 Unity 编辑器中初始化。
- 在
Start()方法中,添加以下代码:
contentPosBehaviour = GetComponent<ContentPositioningBehaviour>();
这将检索包含脚本的 GameObject 的 ContentPositioningBehaviour 组件。
- 在
Update()方法之后,创建一个新的方法:
public void SwitchMultipleChairs()
{
if (!multipleChairs)
{
chairButton.GetComponent<UnityEngine.UI.Image>().sprite = buttonSprites[1];
contentPosBehaviour.DuplicateStage = true;
multipleChairs = true;
}
else
{
chairButton.GetComponent<UnityEngine.UI.Image>().sprite = buttonSprites[0];
contentPosBehaviour.DuplicateStage = false;
multipleChairs = false;
}
}
当此方法被调用时,它会检查当前状态是一把椅子还是多把椅子。相应地切换 UI 按钮的图像,并调整 ContentPositioningBehaviour 类的 DuplicateStage 参数以允许一个或多个相同的椅子实例。然后,它将 multipleChairs 设置为 true 或 false 以跟踪当前状态。
- 在 Unity 编辑器中,将脚本拖到 Plane Finder 上。或者,在检查器窗口中,点击 Add Component|On The Go Handler:

将创建的脚本添加到 Plane Finder GameObject
-
在 On The Go Handler 脚本中,将按钮拖到 Chair Button 字段,并从 @MyAssets|Images 中按顺序选择两个精灵,椅子和电影院(见以下截图)。
-
从内容定位行为下拉菜单中取消选中 Duplicate Stage,以便它从单个椅子开始:

在检查器窗口中将相应的元素分配给 OnTheGoHandler 脚本
- 最后,选择按钮,在 On Click () 方法中,在底部选择 Plane Finder 并选择 On The Go Handler|SwitchMultipleChairs 函数:

在检查器窗口中选择按钮的 OnClick() 方法行为
- 在添加任何新功能之前,我们需要在移动设备上构建此应用。按 Ctrl + Shift + B 或转到 File|Build Settings...:

构建设置面板以在移动设备上构建和运行应用
- 按 Build And Run,给你的
.apk文件命名,并在移动设备上运行。将相机对准地面,直到出现一个小图标,标记地面水平:

白色方块显示了虚拟对象将被放置的地面上的点
- 四处走动并在屏幕上轻触以放置一把椅子。现在,你可以绕着虚拟椅子走动,从不同的角度观看它:

放置在真实环境中的虚拟红色椅子
- 按钮切换到多椅子模式,移动相机,并将多个椅子放置在房间的各个角落:

两个虚拟椅子,一个挨着一个
很可能,在您的第一次尝试中,椅子的大小不会如您所愿,或者阴影不会与真实情况相符。此外,椅子将始终朝前,因此您必须围绕房间移动,然后再将其放置在期望的位置。让我们改进这些小细节,使应用程序更具吸引力。
改进应用程序
现在,我们将改进当前应用程序,使其对用户更具吸引力:
- 首先,尝试添加一个新的方向光(右键单击现有的一个并按复制),然后调整其旋转、强度和/或阴影类型。在这种情况下,我们放置了两个灯,旋转值分别为 (
-30,-20,0) 和 (30,20,0),并且没有阴影,创建了一个颜色较浅的椅子:

一个方向光的值
- 现在,让我们使地板的视觉参考更加明显:选择 Plane Finder GameObject,并在检查器窗口中双击位于 Plane Finder Behaviour 脚本中的 DefaultPlaneIndicator 元素。这将打开原始元素:

在检查器窗口中选择 DefaultPlaneIndicator
- 从层次结构窗口中选择 DefaultIndicator 子项。然后,在检查器窗口中,将其大小增加到
0.05并将默认图像更改为 reticle_ground_surface:

DefaultIndicator GameObject 的组件在检查器窗口中
- 在场景窗口中右键单击王子 GameObject 并选择 3D Object|Quad,给椅子添加一个旋转指示器,以便我们在屏幕上使用两个手指时它会出现:

创建一个 prince GameObject 的 Quad 元素子项
- 将
placement_rotate图像从项目窗口拖到层次结构窗口中的旋转 GameObject 上,将其转换为纹理,并将材质的渲染模式设置为 Cutout:

Quad 材料的属性在检查器中
- 调整其位置和旋转,使其出现在地面舞台的中间:

座位周围地面中间的 Quad
- 现在,在 @MyAssets|Scripts 文件夹中创建另一个脚本。命名为
ChairHandler.cs并将其附加到王子 GameObject:

将新创建的脚本附加到其上的王子 GameObject
- 双击脚本以在 Visual Studio 中打开它:

ChairHandler 脚本在 Visual Studio 中
- 在课程开始时添加以下变量:
public GameObject rotateGO;
private float rotateSpeed = 0.8f;
第一个变量指的是我们之前创建的 Quad GameObject(带有旋转箭头图像)。第二个变量控制椅子的旋转速度。
- 在
Start()方法中,添加以下代码:
rotateGO.SetActive(false);
通过这种方式,我们隐藏了旋转箭头,直到椅子实际上在旋转。
- 现在,在
Update()方法中,添加以下代码:
Touch[] touches = Input.touches;
if (Input.touchCount == 2 && (touches[0].phase == TouchPhase.Moved || touches[1].phase == TouchPhase.Moved))
{
rotateGO.SetActive(true);
Vector2 previousPosition= touches[1].position - touches[1].deltaPosition - (touches[0].position - touches[0].deltaPosition);
Vector2 currentPosition = touches[1].position - touches[0].position;
float angleDelta = Vector2.Angle(previousPosition, currentPosition);
Vector3 cross = Vector3.Cross(previousPosition, currentPosition);
Vector3 previousRotation = transform.localEulerAngles;
if (cross.z > 0)
{
transform.localEulerAngles = previousRotation - new Vector3(0, angleDelta * rotateSpeed, 0);
}
else if (cross.z < 0)
{
transform.localEulerAngles = previousRotation + new Vector3(0, angleDelta * rotateSpeed, 0);
}
}
else
{
rotateGO.SetActive(false);
}
上述代码检索来自屏幕的触摸。如果是两个触摸(两个手指触摸屏幕)并且至少有一个在移动,它执行以下操作:
-
使旋转图像可见。
-
获取触摸的位置。
-
计算最后手指位置和当前位置之间的角度,并相应地旋转椅子。当用户停止旋转椅子时,旋转图像再次隐藏。
-
最后一步是将 Quad GameObject 从 Hierarchy 拖到 Inspector 窗口中 ChairHandler 脚本的 Rotate GO 字段。
-
现在,你可以直接按 Ctrl + B 来构建和运行项目,或者通过 File|Build And Run 来做。正如你所看到的,地面上的标记现在更加明显了:

新的地面参考标记
- 现在,你还可以旋转椅子,看看它放在那里的样子:

当用户用两只手指旋转椅子时出现的旋转箭头
这样,我们就完成了 AR 家具查看器。
摘要
在本章中,我们学习了 Vuforia 的一个功能:地面平面。我们创建了一个项目,将虚拟椅子放置在现实场景中,并允许我们通过触摸屏(旋转它们)和简单的 UI 按钮来操作它们(乘以它们)。
到现在为止,你将更好地理解 Vuforia 的工作原理,如何在 Unity 中创建 Vuforia 元素,以及如何在其中创建一个完全功能的地面平面示例。通过在这个项目开发过程中获得的技术,你可以通过添加新的 3D 模型、新的 UI 元素或更新当前脚本以在应用程序中包含更多功能来改进它。
你还可以更好地了解 AR 在零售领域的应用,以便你可以根据个人或专业需求调整当前项目。正如我们在本章开头提到的,以及我们一直在看到的,应用程序可以很容易地更改以显示其他类型的家具、装饰、地毯或任何你想要在表面上展示并从不同角度观察的产品。
在下一章中,我们将通过查看图像目标和在 Moverio AR 眼镜中部署应用程序来进一步探索 Vuforia 的可能性。
进一步阅读
从这里,你可以尝试使用 Vuforia 的“空中”选项,它不是将附着在地面上的物体放置在地面上,而是将它们放置在地面的距离之外。这对于在墙上放置物体,如画框、图片等,或者当与无人机等飞行物体一起工作时非常有用。它们的使用非常相似;你不需要创建“平面查找器”和“地面平面舞台”,而是创建一个“空中位置器”和“空中舞台”。
你还可以从 Unity 资产商店下载 Vuforia 核心示例(assetstore.unity.com/packages/templates/packs/vuforia-core-samples-99026),其中包含地面平面及其功能的完整示例。
第七章:使用 Vuforia 和增强现实眼镜进行自动化增强现实
在本章中,我们将更深入地探讨 Vuforia,这是我们之前在第六章中介绍过的 SDK,即使用 Vuforia 的零售增强现实。您将学习如何使用该框架以及增强现实眼镜,更具体地说,是 Epson Moverio BT-350 型号,您还将学习如何使用 Vuforia 图像识别功能来创建一个应用,逐步引导操作员在工业工作中,以及如何修改场景以便将其集成到您的增强现实眼镜中。
重要提示:为了完成本章,您将需要拥有增强现实眼镜来在此基础上构建。尽管我们已经将内容结构化,以便您可以使用移动 Android 设备跟随大部分过程,但您只能在能够启动真实眼镜上的项目时,才能看到最终结果、移动设备视图中的差异以及增强现实透视设备提供的可能性。
本章有三个主要目标:首先,为了更全面地了解 Vuforia 的工作原理,以便您可以在本书的范围之外扩展和改进当前示例。第二个目标是了解增强现实在工业领域,特别是在自动化方面的可能性。您将看到,增强现实不仅是一种视觉上吸引人的技术,而且它还可以在工作过程中指导操作员,减少培训时间和操作过程中的可能错误。目标是为您提供必要的技能,以复制和调整当前项目以满足您的需求。最终目标是介绍一款增强现实头戴设备,例如爱普生 Moverio AR 眼镜,解释它们的工作原理,并轻松地将 Vuforia 与它们集成。
在工业领域使用增强现实眼镜而不是平板电脑可以是一个有价值的资产,因为它允许操作员在工作的同时双手空闲。以下图片展示了一副增强现实眼镜:

爱普生 Moverio BT-350 增强现实眼镜
本章将涵盖以下主题:
-
在自动化中使用增强现实
-
探索 Vuforia
-
在 Vuforia 中开发基于图像的增强现实
-
为增强现实眼镜创建工业指南
技术要求
本章的技术要求如下:
-
支持 Unity 3D 的计算机(请参阅最新要求
unity3d.com/es/unity/system-requirements)。本章的示例项目是在 Windows 10 x64 计算机上开发的。 -
Unity 3D(本书中为 2019.1.2f1)。
-
微软 Visual Studio Community 2017(包含在 Unity 安装中)。
-
Unity 3D 中包含的 Vuforia 最新版本(本书中为 8.3.8)。
-
爱普生 Moverio BT-350 增强现实眼镜。
本章的资源和相关代码文件可以在以下位置找到:github.com/PacktPublishing/Enterprise-Augmented-Reality-Projects/tree/master/Chapter07。
其他增强现实眼镜(来自 Moverio 和其他公司)可能也会与这个例子兼容。然而,需要考虑一些因素,例如,它们的操作系统必须是 Android 4.1 或更高版本(由 Unity 3D v2019 要求)。
让我们从自动化中的增强现实开始吧。
在自动化中使用增强现实
第四次工业革命的到来,也被称为工业 4.0,极大地推动了增强现实(AR)在工业环境中的应用。工业 4.0 的核心是数字化和互联性,而诸如增强现实(AR)、虚拟现实(VR)、物联网(IoT)、大数据分析(BDA)、增材制造(AM)、网络物理系统(CPS)和人工智能(AI)等技术已成为这次工业革命的基础。
增强现实是物联网和大数据的自然接口和连接。它允许工人以简单且吸引人的方式可视化并交互工厂来自传感器和设备的数据,无论是使用移动设备还是增强现实头盔。
自动化中增强现实的应用可以从员工的面部识别到访问具体机器,再到通过增强现实眼镜进行现场生产过程的实时监控或远程访问和控制系统。
介绍场景和流程
对于这个项目,我们将创建一个可用于生产、维护和培训的逐步指南。执行任务的用户将获得如何正确执行任务的指导,以及访问如蓝图图纸或 PDF 文档等有用信息。
为了说明这一点,我们将以大众甲壳虫(汽车)为例。我们将使用三张图片作为目标(侧面、车尾闭合尾箱的视角,以及车尾打开尾箱的视角)来模拟一个从汽车侧面开始,然后移动到检查汽车发动机状态的操作员,同时从增强现实眼镜中接收信息。在真实环境中,这些图片将与真实的汽车(或工业设备)相对应。
我们将在本项目中使用的图像已从以下链接获取:
-
甲壳虫汽车的 3D 模型:
sketchfab.com/3d-models/beetlefusca-version-2-2f3bea70178345c8b7cc4424886f9386 -
蓝图:
getoutlines.com/blueprints/6826/1968-volkswagen-beetle-sedan-blueprints -
PDF 文件中的图像:
getoutlines.com/blueprints/6943/1972-volkswagen-beetle-1500-sedan-blueprints
在下一节中,我们将简要介绍 Vuforia,然后再开始开发指南项目。
探索 Vuforia
正如我们在第六章,“使用 Vuforia 的零售 AR”中讨论的那样,Vuforia 是自 2017.2 版本以来集成到 Unity 中的最古老和最知名的 AR SDK 之一。它提供了多个 AR 功能,如图像识别、地面平面识别、模型检测等。您可以在engine.vuforia.com/features.html找到所有可用功能。对于这个项目,我们将专注于图像识别。
在第六章,“使用 Vuforia 的零售 AR”,在“探索 Vuforia”部分,我们解释了在 Unity 项目中首次集成 Vuforia 的步骤。请遵循该部分中的步骤 1-7,但更改以下参数:
-
Unity 项目名称(步骤 3):
AR_Automation -
场景名称(步骤 4):
ARGuide -
产品名称(步骤 6,玩家设置):
AR Guide
最后,将灯光的旋转点或轴设置为 X:20,Y:0,和 Z:0,并将其放置在 ARCamera 内部(作为一个子级)以保持其方向性:

带有新值和 ARCamera 子级的方向光
现在我们已经在项目中准备好了 Vuforia 引擎,让我们开始 AR 创建过程。
在 Vuforia 中开发基于图像的 AR
Vuforia 最强大的功能之一是图像识别。Vuforia 引擎可以处理任何.jpeg或.png图像(我们的 AR 标记或目标)并提取其主要特征。它将稍后比较这些特征与来自移动设备或 AR 眼镜摄像头的实时图像,以在现实世界中找到该标记并将虚拟元素叠加在其上以创建 AR。在我们的案例中,我们将使用从 3D 模型中提取的三张甲壳虫汽车的图像。然而,图像可以来自任何来源,例如现实生活中的图片或计算机设计的图像。
下一节将展示我们如何在 Vuforia 中创建目标。
创建目标
当与图像一起工作时,Vuforia 提供了两种不同的选项:
-
设备数据库是通过对 Vuforia Target Manager 创建并通过本地项目下载和包含的图像目标组。
-
云识别指的是直接在线托管和管理图像目标组。
对于这个项目,我们将使用第一个选项。数据库,在 SDK 中也称为数据集,是一组目标。它们有助于大量目标的分类,以及内存和 CPU 的使用。数据库可以在运行时动态加载/卸载,并且所有加载的数据库中的目标都将添加到 AR 搜索中。在撰写本书时,数据库中目标数量的硬限制尚不存在,尽管 Vuforia 出于性能原因建议不要超过 1,000。
要创建我们自己的数据库和目标,我们必须登录到 Vuforia 开发门户并前往目标管理器,如下所示:
-
登录或注册(如果您没有账户)以进入页面:

“目标管理器”页面
- 点击右上角的“添加数据库”以创建新数据库。因为我们将使用 Beetle 图像作为目标,所以给数据库命名为
Beetle:

创建新数据库
-
现在,点击创建的数据库,然后点击添加目标。
-
点击浏览按钮,从项目的资源文件夹中的
Targets文件夹选择Side.jpg图像。一旦上传,您将看到底部的名称字段将自动填充。给它一个宽度值为1并点击添加:

创建新目标
- 目标将自动创建,旁边您将看到一些星星,如以下截图所示。这些星星表示图像将被 AR 软件识别的程度。四颗或五颗星星是好的目标。
如果您有任何疑问或想了解更多关于创建目标时出现的其他选项的信息,您可以查看library.vuforia.com/articles/Solution/How-To-Work-with-Device-Databases.html。
- 使用
Back_closed.jpg和Back_open.jpg图像以及相同的宽度1重复步骤 4和步骤 5,以便它们在 Unity 编辑器中具有相似的缩放:

带有 Beetle 数据库及其目标的“目标管理器”页面
-
创建了三个目标后,点击下载数据库(全部),选择 Unity 编辑器,然后点击下载。它将下载一个
Beetle.unitypackage文件,我们将将其导入到项目中。 -
双击
Beetle.unitypackage文件将其导入 Unity。您也可以通过点击 Assets|导入包|自定义包…并选择文件来从 Unity 编辑器导入:

要导入到 Unity 中的目标数据库文件
- 这将把数据库添加到一个新创建的
StreamingAssets/Vuforia文件夹中,并将三个目标的压缩图像添加到Editor/Vuforia/ImageTargetTextures/Beetle文件夹中。
现在我们已经将数据库包含在我们的项目中,我们将按照以下步骤将三个目标添加到场景中:
- 右键单击层次结构窗口,然后单击 Vuforia Engine|Image。这将在我们场景中创建一个 ImageTarget 对象:

将 Vuforia ImageTarget 添加到场景中
- 默认情况下,ARCamera 和 ImageTarget 将在同一位置,相机上不会显示任何内容。使用旋转选项卡,将相机在 X 轴上旋转
90度,并向上移动3个单位,直到目标在视图中:

ARCamera 变换值
- 创建其他两个 ImageTargets 并将它们移动到三个目标都在视图中。将它们命名为
Target_Side、Target_Close和Target_Open,以便您可以区分它们:

场景中的三个目标
- 默认情况下,ImageTarget 代表第一个数据库中找到的第一个目标,按字母顺序排序。要更改它,请选择层次结构窗口中的
Target_Side,然后在检查器窗口中,在 Image Target Behavior 组件下选择其图像。对Target_Open也做同样的操作。如果您愿意,可以使用缩放选项卡调整目标的大小,并将它们移动到看起来相似并占据整个相机宽度以获得更好的视图:

更改目标的图像引用
我们将在下一节学习如何添加测试立方体。
添加一些测试立方体
为了快速测试我们的场景,让我们创建三个不同的对象,以便在每个目标上方进行可视化:
-
右键单击
Target_Side并选择 3D Object|Cube。 -
缩小它,以免完全隐藏目标。
-
对于
Target_Close,创建一个 3D Object|Sphere 而不是立方体,对于Target_Open,创建一个 3D Object|Capsule。 -
也缩小它们,以便目标部分在视图中。由于这只是为了测试目的,我们不会向这些对象添加任何材质或纹理:

测试每个目标内的 3D 对象
现在,让我们获取我们的 Vuforia 密钥,以便我们可以测试应用。
获取密钥
为了测试应用或在设备上运行它,我们需要在 VuforiaConfiguration 对象中提供一个许可证密钥。由于我们已经登录到 Vuforia 页面创建目标,我们现在将获取所需的密钥。让我们开始吧:
-
前往
developer.vuforia.com/vui/develop/licenses的许可证管理页面。 -
在许可证管理选项卡上,选择获取开发密钥以获取在开发期间使用的免费密钥。
-
给它起一个应用的名字,
AR Guide,阅读并接受条款,然后按确认。 -
选择您新创建的许可证并复制密钥。
-
现在,前往 Unity 编辑器并从场景中选择 ARCamera。
-
在检查器窗口中点击“打开 Vuforia 引擎配置”按钮以打开通用 Vuforia 配置:

打开 Vuforia 引擎配置按钮
- 将你的密钥粘贴到“应用许可证密钥”字段中:

在检查器窗口中的 Vuforia 许可证密钥字段
现在,让我们测试应用以检查我们的 AR 场景是否已正确设置。
测试应用
一旦场景已配置并添加了密钥,点击顶部工具栏中的播放按钮并将摄像头指向三个目标图像。当你指向它们时,你将看到每个目标中出现的不同 3D 对象。
如果你选择在游戏视图的右上角最大化播放,你将能够更好地看到场景。
下一个图像显示了当摄像头指向它时,汽车侧方的立方体出现:

在游戏视图中,立方体对象出现在目标侧目标上方
你可以在项目窗口的Assets/ Editor/Vuforia/ImageTargetTextures/Beetle文件夹中找到这些图片。双击它们在电脑上打开,然后打印它们或直接使用摄像头指向它们。
现在我们已经设置了基本功能,让我们创建完整的应用。
为 AR 眼镜创建工业指南
现在我们已经准备好了基本设置,我们将创建一个指南,指导工人如何逐步进行汽车维护过程。应用将显示带有彩色图片和箭头的说明,这些箭头标记了他们需要查看的汽车部件。它还将提供一个帮助 PDF 文件,他们可以在需要时打开查阅。
应用的一般工作方式如下:
- 当应用启动时,它将要求工人指向汽车的侧面以开始过程:

初始信息
- 当用摄像头指向汽车侧面(目标侧)时,其蓝图将出现在其上方,用红色指示引擎中的问题:

标记引擎的红色蓝图
- 当操作员触摸红色方块时,应用将指示他们前往汽车的后面:

用户触摸引擎时的信息
- 当用摄像头指向汽车后面(目标靠近)时,应用将通过闪烁的箭头指示打开行李箱:

打开行李箱的信息
-
一旦工人已经打开行李箱并指向引擎(目标打开),应用将指示用户需要移除并更换左上角的火花塞。
-
在屏幕的一侧,将提供带有指令的帮助 PDF 文件,以防工人需要它们。
-
当操作员完成更换部件后,他们将按下一个按钮以确认他们已完成任务:

指向火花以替换的箭头和此步骤的 UI 按钮
注意:我们将使用的内容仅用于演示目的,并不对应此程序的真正指令。
在下一节中,我们将向我们的项目中添加所需的内容。
准备材料
对于这个项目,我们将使用一些需要导入到项目中并定制的媒体内容。我们必须将其放入项目中,然后在我们的场景中使用它。为此,请按照以下步骤操作:
- 在项目窗口的
Assets文件夹中创建一个新文件夹,命名为@MyAssets。然后,在它里面创建两个其他文件夹,分别命名为Images和Scripts:

在项目窗口中创建新文件夹
-
从本章的资源中,将
arrow.png、blueprint.png、icon_file.png和icon_home.png图像文件拖放到您刚刚创建的Images文件夹中。 -
选择名为图标的图像,在检查器窗口中,将它们的纹理类型更改为 Sprite(2D 和 UI),这样我们就可以在 UI 中使用它们:

更改图标纹理类型
- 在项目窗口的
Assets/StreamingAssets文件夹中创建一个新的文件夹,命名为PDF,并将WorkOrder_0021.pdfPDF 文件拖放到其中:

StreamingAssets/PDF 文件夹中的 PDF 文件
添加 UI
对于这个项目来说,一个重要的事情是目标设备不是手机或平板电脑,而是 AR 眼镜。当使用眼镜时,场景视图被复制(每只眼睛)并且比平板电脑或手机小。因此,UI 及其元素的大小必须相应调整。
作为总结,对于本指南,我们需要以下元素:
-
主信息:占据屏幕大部分的文本,提供主要指令(指向汽车的侧面,前往后面等)。
-
底部信息:放置在屏幕底部的指示文本,提供与 AR 元素结合的次要指令(触摸红色元素以查看指令,打开行李箱,更换部件等)。
-
PDF 按钮:用于 PDF 格式的额外信息的按钮。
-
主页按钮:返回初始屏幕。
让我们一步步创建它们:
- 首先在层次窗口中创建一个画布对象:

在场景中添加画布
当创建 Canvas 对象(任何其他 UI 元素的父对象)时,会自动创建一个事件系统对象,该对象负责与 UI 连接的用户事件。如果您在创建 Canvas 之前尝试创建任何 UI 组件(例如,文本、按钮等),Unity 将创建一个 Canvas 元素(及其 EventSystem 对象),并将新组件作为其子组件。
- 在检查器窗口中,将画布组件的渲染模式从屏幕空间 - 覆盖更改为世界空间,并选择 ARCamera 作为事件相机。这样,画布就被放置在 3D 世界中,而不是固定,可以移动/缩放。在矩形变换组件中,输入图像的值,以便画布位于相机前面:

Canvas 游戏对象的值
- 让我们创建主要消息。在层次结构窗口中右键单击画布元素,并选择 UI|Text。将其命名为
Main_message:

在画布元素内创建新文本
- 在层次结构窗口中,更改矩形变换组件的值以匹配以下截图。移除默认文本,更改对齐方式使其在屏幕中居中,勾选最佳拟合复选框以便文本填充容器,将最大尺寸设置为
80以确保足够大,并将颜色更改为白色:

Main_message 中矩形变换和文本组件的值
- 我们现在将创建一个次要信息面板。由于它与前面的面板非常相似,我们可以直接右键单击前面的面板并选择复制:

复制消息
- 将其名称更改为
Bottom_message,并更改其矩形变换值,使其位于屏幕底部:

新消息的值
- 要创建按钮,请右键单击画布元素并选择 UI|Button:

在画布上创建按钮元素
-
从它上面移除文本,并将按钮名称更改为
Home_button。 -
在矩形变换中,选择将其锚定到左下角,并从图像中复制值以将其放置在屏幕左下角,并为其眼镜设置适当的大小:
-
在图像组件中,选择
icon_home图像作为源图像,并在按钮组件中更改按下颜色。这样,当按钮被点击时,它将从白色变为蓝色:

Home_button 在检查器中的值
- 复制按钮以创建其副本,并将其命名为
File_button。更改其矩形变换,以便您可以将其定位在屏幕右上角,并将其源图像更改为 icon_file,如下所示:

File_button 的值
- 现在,从头开始创建最后一个按钮,命名为
OK_button,并将其放置在屏幕的右下角。将其正常颜色更改为浅绿色:

Ok_button 元素的值
- 在按钮上右键单击 Text 子项,并更改 Rect Transform 和 Text 组件参数,使其与以下截图中的内容匹配:

Ok_button 内部 Text 元素的值
- 您的场景和游戏视图现在应该看起来像这样:

带有创建的 UI 的场景和游戏视图
注意,如果您在工具栏中按下播放按钮,您会看到当真实摄像头的视频流启动时,UI 消失了。不要担心这一点,因为我们将在本节的后面调整它。
现在 UI 元素已经准备好了,我们将添加虚拟元素,这些元素将在 AR 中显示,以及与它们相关的逻辑。
安装 AR 场景
我们将要做的第一件事是修改场景中每个目标附加的DefaultTrackableEventHandler.cs脚本。此脚本确定在现实世界中找到或丢失目标时要执行的操作;默认情况下,它显示和隐藏附加到该目标任何子项的 Renderer、Collider 和 Canvas 元素。
对于我们的应用程序,我们需要知道何时找到目标,为此,我们将在脚本中添加一个变量。
对于这个项目,我们只需要在脚本中做一点小的修改。然而,如果您想添加更多代码来控制目标何时被找到或丢失,最好创建一个新的类,该类继承自ITrackableEventHandler,例如DefaultTrackableEventHandler,这样您就始终有一个参考类可以返回,以防代码中出现问题。
在项目窗口中,双击此脚本,您可以在 Vuforia|Scripts 中找到它。当 Visual Studio 窗口打开时,我们需要将public bool found = false;变量添加到变量中:
然后,在OnTrackingFound()方法内部,在末尾添加found = true;。
在OnTrackingLost()方法内部,在末尾添加found = false;。
这样,我们就可以从任何其他类中使用这个变量来知道是否找到了目标。
回到 Unity 中,让我们开始添加 AR 元素。为此,首先,删除测试 3D 立方体、球体和胶囊。
现在,我们将查看第一个目标:
- 在 Target_Side 上右键单击并创建一个 3D Object|Plane:

创建一个新的平面
- 从项目窗口中,将蓝图图像拖到飞机上以使其成为其纹理:

将蓝图图像作为飞机的纹理
- 在检查器窗口中,将其名称更改为
Blueprint。在底部材质面板中,将渲染模式更改为淡入,使其透明且平滑。现在旋转、缩放和平移平面,直到蓝图与下面的汽车匹配,如下面的截图所示:

目标上方的蓝图及其在检查器窗口中的值
重要!保持 Y 位置值为0.01,以确保绘图位于目标上方,但不要离目标太远。这是为了确保 AR 正常工作,并且蓝图不会因为与目标分离太远而闪烁。
- 现在,我们必须创建另一个覆盖发动机区域的平面,以便当用户触摸它时,它为他们提供方向。创建另一个名为
Engine的 Blueprint 子平面。移动和调整其大小,直到它适合发动机区域(在蓝图上用红色标记):
重要!将其保持在蓝图上方(Y 位置0.015或0.02)。
下一个图像显示了放置在发动机区域上的新灰色平面:

位于发动机区域上的新平面
现在,我们必须使这个平面不可见,因为它只起激活器的作用。在检查器面板中,通过点击右上角的齿轮并选择移除组件来移除其 Mesh Renderer 组件。现在,只有选择它时你才能看到平面:

从平面上移除 Mesh Renderer 组件
让我们转到第二个目标。这个目标将显示一个箭头,指示用户打开树干:
-
右键点击 Target_Close,创建一个新的 3D 对象|平面,并将其放置在树干中间。
-
将箭头图像拖到平面上,使其成为其纹理。
-
在检查器窗口中,将平面命名为
Arrow。请记住将 Y 位置设置为0.01。在材质字段中,将渲染模式设置为淡入,并将 Albedo 颜色更改为浅蓝色:

箭头平面的值
- 要添加箭头的闪烁效果,在
@MyAssets/Script文件夹中创建一个新的 C#脚本,并将其命名为Blinking.cs:

将新脚本添加到@MyAssets/Scripts 文件夹
- 双击它以在 Visual Studio 中打开:

Visual Studio 中的闪烁脚本
- 现在,添加以下行以创建闪烁效果。首先,声明以下变量:
private IEnumerator coroutine;
private bool blinking;
coroutine是 Unity 中的一个特殊函数,它暂停执行并将控制权交回调用方法,直到满足某个条件,然后从上次停止的地方继续执行。我们将用它来每半秒闪烁一次。
- 现在,在
Start()方法内部,包含以下初始化行:
coroutine = BlinkingArrow();
blinking = false;
- 在
Update()方法之后添加coroutine:
private IEnumerator BlinkingArrow()
{
while (true)
{
GetComponent<MeshRenderer>().enabled = false;
yield return new WaitForSeconds(0.5f);
GetComponent<MeshRenderer>().enabled = true;
yield return new WaitForSeconds(0.5f);
}
}
coroutine 的常规暂停命令是 yield return null;,它暂停执行一帧。对于这个 coroutine,我们使用了 yield return new WaitForSeconds(0.5f); 来告诉 coroutine 在执行下一行之前等待半秒。使用此代码,我们使脚本附加到的 GameObject(箭头)的 MeshRenderer 组件每半秒出现和消失一次。
- 在
Update()方法内部,我们将使用coroutine以确保箭头仅在检测到目标时闪烁,否则隐藏。使用闪烁布尔值,我们将验证coroutine只启动一次:
if (GetComponentInParent<DefaultTrackableEventHandler>().found && !blinking)
{
blinking = true;
StartCoroutine(coroutine);
}
else if (!GetComponentInParent<DefaultTrackableEventHandler>().found && blinking)
{
blinking = false;
StopAllCoroutines();
GetComponent<MeshRenderer>().enabled = false;
}
- 在 Unity 编辑器中,回到检查器窗口,点击添加组件,并将闪烁脚本添加到箭头平面上:

将新脚本添加到平面上
最后,让我们转到第三个目标,它将有一个另一个箭头:
-
右键单击箭头游戏对象并按复制。
-
然后,右键单击 Target_Open 游戏对象并粘贴它。
-
移动和旋转它,直到它指向树干的左上角:

指向树干不同位置的两个箭头
目前,如果我们按下顶部工具栏上的播放按钮,当我们指向每个标记时,我们会看到蓝图和箭头出现。然而,我们需要将它们转换成逐步指南,只有当上一个步骤完成时才会显示指令。我们将在另一个脚本中添加该逻辑:
-
在项目窗口中,在
@MyAssets/Scripts文件夹中,右键单击并创建另一个 C# 脚本。 -
将其命名为
MainHandler.cs并双击它以在 Visual Studio 中打开:

Visual Studio 中的 MainHandler 脚本
- 首先向库中添加 Vuforia 的
UnityEngine.UI:
using Vuforia;
using UnityEngine.UI;
- 然后,添加以下变量:
public DefaultTrackableEventHandler targetSide;
public DefaultTrackableEventHandler targetClose;
public DefaultTrackableEventHandler targetOpen;
public GameObject mainMessage;
public GameObject bottomMessage;
public GameObject fileButton;
public GameObject okButton;
它们都是 public 的,因为我们将从 Unity 编辑器初始化它们。它们引用了我们将要与之交互的不同场景元素,包括目标对象和 UI 元素。
- 现在,在变量之后添加此属性:
public bool Finished { get; set; }
它也是 public 的,因为当用户按下 Done 按钮时,我们也将从编辑器分配它。
- 最后,添加以下私有变量,它是一个枚举,用于控制应用的每个状态:
private enum State
{
Init = 0,
Side = 1,
Engine = 2,
Close = 3,
Open = 4,
Plug = 5
}
private State state;
- 现在,让我们在
Update()方法之后添加一些方法。创建一个名为ShowElements()的新方法:
private void ShowElements()
{
}
它将在类内部私有使用,根据应用的状态显示或隐藏不同的组件。此方法还将控制每个步骤中显示信息的标记。
- 我们将在
ShowElements()内部创建一个switch调用:
switch (state)
{
case State.Init:
break;
case State.Side:
break;
case State.Engine:
break;
case State.Close:
break;
case State.Open:
break;
case State.Plug:
break;
}
在这里,我们将告诉方法根据应用当前处于哪个状态执行不同的操作。
- 在
State.Init情况下,添加以下内容:
targetSide.gameObject.SetActive(true);
targetOpen.gameObject.SetActive(false);
targetClose.gameObject.SetActive(false);
mainMessage.SetActive(true);
bottomMessage.SetActive(false);
fileButton.SetActive(false);
okButton.SetActive(false);
mainMessage.GetComponentInChildren<Text>().text = "Point with the camera at the side of the car to start the maintenance process.";
在这里,我们只显示targetSide目标。为了确保用户无法看到其他两个目标的说明,我们只激活主要信息并添加文本到其中。
- 在
State.Side情况中,添加以下内容:
mainMessage.SetActive(false);
bottomMessage.SetActive(true);
bottomMessage.GetComponentInChildren<Text>().text = "Touch the red components to see instructions.";
当用户使用相机找到targetSide时,我们进入此状态,在此状态下,我们停用主要信息并显示底部信息。
- 在
State.Engine情况中,添加以下内容:
targetClose.gameObject.SetActive(true);
mainMessage.SetActive(true);
bottomMessage.SetActive(false);
mainMessage.GetComponentInChildren<Text>().text = "One of the spark plugs is broken. Point at the trunk and follow the steps.";
如果用户触摸了红色组件,我们将激活下一个目标并显示带有如何找到它的说明的主要信息。
- 在
State.Close情况中,添加以下内容:
targetSide.gameObject.SetActive(false);
targetOpen.gameObject.SetActive(true);
mainMessage.SetActive(false);
bottomMessage.SetActive(true);
bottomMessage.GetComponentInChildren<Text>().text = "Open the trunk to access the engine.";
用户已经找到了targetClose,因此我们停用前一个并激活下一个。我们还在底部添加了一条信息以打开树干。
- 在
State.Open情况中,添加以下内容:
targetClose.gameObject.SetActive(false);
fileButton.SetActive(true);
okButton.SetActive(true);
bottomMessage.GetComponentInChildren<Text>().text = "Take the spark plug out and replace it. When you finish press 'Done'";
在这里,我们激活两个按钮:fileButton用于查看 PDF,okButton用于完成流程。
- 在
State.Plug情况中,添加以下内容:
targetOpen.gameObject.SetActive(false);
mainMessage.SetActive(true);
bottomMessage.SetActive(false);
fileButton.SetActive(false);
okButton.SetActive(false);
mainMessage.GetComponentInChildren<Text>().text = "Well done, you can take a coffee now :)";
这是最后一步,因此我们将隐藏按钮和目标,只留下结束信息可见。
- 现在,创建另一个名为
NextStep()的方法:
private void NextStep()
{
state++;
ShowElements();
}
我们将调用此方法从一步转换到下一步。
- 添加另一个名为
ResetInstructions()的方法:
public void ResetInstructions()
{
state = 0;
ShowElements();
}
此方法为public,因为它将由编辑器通过 Home 按钮调用。它将转到应用初始状态。
- 现在,让我们修改
Start()方法,将其转换为在隐藏第二个和第三个目标之前等待 Vuforia 初始化的coroutine。否则,它可能无法识别它们:
IEnumerator Start()
{
while (!VuforiaARController.Instance.HasStarted) //waits until Vuforia has instanciated the three markers
yield return null;
state = State.Init;
ShowElements();
}
- 最后,在
Update()方法中,输入从一步到下一步的逻辑转换。因此,当以下情况发生时,应用将从一个步骤跳转到下一个步骤:
-
在
Init、Engine和Close状态下,应用检测相应的目标(侧面、关闭、打开) -
在
Side状态下,用户触摸屏幕上的汽车引擎区域 -
在
Open状态下,用户触摸了完成按钮:
if ((state == State.Init && targetSide.found) || (state == State.Engine && targetClose.found) || (state == State.Close && targetOpen.found))
{
NextStep();
}
else if (state == State.Side)
{
if (Input.GetMouseButtonDown(0))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
if (hit.transform.name == "Engine")
NextStep();
}
}
else if (state == State.Open && Finished)
{
Finished = false;
NextStep();
}
一旦我们完成了脚本,回到 Unity:
- 将脚本从项目窗口拖到层次结构窗口中的 ARCamera 游戏对象。或者,点击 ARCamera,在检查器窗口中,点击添加组件并选择脚本。将场景中的元素填写到 Main Handler 脚本中的每个字段:

主处理程序及其在 ARCamera 游戏对象中的字段
- 选择 Home_button。然后,在检查器窗口中,在点击(OnClick)面板中添加一个新事件,选择 ARCamera,然后选择 ResetInstructions()方法:

在“Home_button”的点击(Click)事件中
- 选择 OK_button。然后,在检查器窗口中,在点击(OnClick)面板中添加一个新事件,选择 ARCamera,然后选择 Finished 属性。勾选复选框,以便每次按下按钮时,Finished 属性都将设置为 true:

在 OK_button 的 OnClick()事件中
现在我们已经准备好了主要功能,让我们配置场景,以便我们可以在眼镜中构建它。
配置眼镜的 AR
这个步骤非常重要,这样我们才能了解眼镜的工作原理.
如果在这个时候,我们在 Moverio 眼镜中编译应用程序,我们将在眼镜屏幕上看到视频流,就像我们使用手机一样。这不是使用 AR 的最佳方式;我们希望背景保持透明,只有 UI 元素和 AR 元素出现在屏幕上。
然而,为了看到眼镜中 AR 的效果和某些特性,我们将编译应用程序,然后进行相关修改。
打开 Moverio 眼镜,并通过 USB 将它们连接到你的电脑。
由于你已经定义了设置,切换到 Android 平台,并在介绍中将当前场景添加到建筑列表中,只需点击Ctrl + B或点击文件|构建和运行(如果你跳过了任何这些步骤,或者如果你不确定,请转到文件|构建设置…并检查是否一切正常)。给.apk文件命名并构建它。
正如我们讨论的那样,你将在眼镜上看到视频流,UI 将比预期的大。现在,先忘记 UI,看看视频流。如果你将视频流与背后的真实世界图像进行比较,你会发现视频流比真实世界小,并且略有偏移(考虑到相机放置在眼镜的一侧)。以下图片显示了这种偏移(考虑到图片只从眼镜的左侧屏幕拍摄,所以偏移比左右两侧结合时更大):

眼镜的 AR 视图
我们必须考虑到这一点,因为当我们移除视频流时,AR 元素在目标上看起来会更小,并且会有偏移。
因此,首先,让我们获取视频反馈。在 Vuforia 中这是一个非常简单的步骤,因为在最新版本中,他们已经将其从代码中移除,并将其放置在 Vuforia 引擎配置中的复选框中。按照以下步骤进行操作:
-
选择 ARCamera 并在检查器窗口中点击打开 Vuforia 引擎配置。
-
在视频背景组件中,取消选中启用视频背景:

在 Vuforia 引擎配置中禁用视频流
- 就这样!通过按Ctrl + B重新构建应用程序,你会看到这次视频没有出现,当你用眼镜指向侧面目标时,只会显示 AR 元素。你也会看到,没有视频流,UI 的大小是正确的。
在视频背景组件之前,还有一个数字眼镜组件。最初,当 Vuforia 首次启用 AR 眼镜时,场景的配置是通过这个组件进行的。然而,现在,它只对 HoloLens 用户有价值,以便为这些眼镜选择配置。
- 最后,让我们使 AR 元素与眼镜可以看到的真实元素相匹配。不幸的是,目前还没有一个确切的方法来做这件事。因此,我们将通过试错法取出位移和尺寸参数,并将它们应用到其他元素上。对于这个项目,这些值如下:
-
位移:x 轴上
+0.5f -
缩放:所有轴上
*2.5
而不是逐个应用它们,在您的 @MyAssets/Scripts 文件夹中创建一个新的脚本,命名为 GlassesHandler.cs,并在 Visual Studio 中打开它。在 Start() 方法内添加以下行:
foreach (Transform child in transform)
{
Vector3 scale = child.localScale;
scale *= 2.5f;
child.localScale = scale;
Vector3 position = child.position;
position += new Vector3(0.5f, 0, 0);
child.position = position;
}
位置、旋转和缩放参数不能直接添加;必须使用一个中间变量。
您的代码应该看起来像这样:

Visual Studio 中的 GlassesHandler 脚本
-
将此脚本拖到三个目标之一,或者通过选择每个目标,在检查器窗口中按“添加组件”,然后选择脚本来添加它。
-
按 Ctrl + B 构建您的应用程序,并查看元素现在是如何覆盖真实元素的。
为了完成我们的应用程序,我们将添加 PDF 功能来帮助操作员完成他们的工作。
添加 PDF 文件
PDF 文件是一个稍微有些困难的任务;由于 Unity 无法内部打开它们,必须使用外部应用程序。在本节中,我们将了解一个简单的调用,我们可以用它来打开 PDF 文件,但它也可以用于其他类型的扩展(如视频)以及通过 URL 打开服务器文件。
重要!首先,您必须在眼镜中安装一个可以打开 PDF 文件的程序,例如 Adobe Reader。请访问 Moverio 网站,了解如何找到和安装这些类型的应用程序。
如您所记得,我们没有将视频和 PDF 文件放置在 @MyAssets 文件夹中,而是在 StreamingAssets/PDF 文件夹中。这个文件夹是 Unity 中的一个特殊文件夹,其中的所有文件都将原样复制到目标设备,这意味着它们根本不会被 Unity 处理。我们不能直接从这个路径加载它们,因此我们将首先将它们复制到一个可访问的路径。
前往 Visual Studio,在 MainHandler.cs 脚本中,让我们添加一些代码来处理这些文件。按照以下步骤进行操作:
- 添加
System.IO库:
using System.IO;
- 在开始处添加以下变量,以指示设备内 PDF 文件的路径:
private string originalPath;
private string savePath;
- 在
Start()方法内初始化它们:
originalPath = Application.streamingAssetsPath + "/PDF/WorkOrder_0021.pdf";
savePath = Application.persistentDataPath + "/WorkOrder_0021.pdf";
- 添加以下
coroutine,它将 PDF 文件从StreamingAssets位置复制到可访问的路径并打开:
private IEnumerator OpenFileCoroutine()
{
WWW www = new WWW(originalPath);
yield return www;
if (www.error != null)
Debug.Log("Error loading: " + www.error);
else
{
byte[] bytes = www.bytes;
File.WriteAllBytes(savePath, bytes);
Application.OpenURL(savePath);
}
}
- 最后,添加以下
public方法来打开 PDF 文件:
public void OpenPDFFile()
{
if (File.Exists(savePath))
Application.OpenURL(savePath);
else
StartCoroutine(OpenFileCoroutine());
}
如果文件已存在于可访问的位置,它将打开它。否则,它将首先复制,然后从协程中打开它。
Application.OpenURL()无论给定路径是 URL 还是内部路径,都会打开它。
在 Unity 编辑器中,选择文件按钮,然后在检查器窗口中,将 OpenPDFfile()调用添加到其 OnClick()事件中:

文件按钮的 OnClick()事件
最后再按一次Ctrl + B,以在眼镜中查看完整的应用程序。
摘要
在本章中,你学习了 Vuforia 的另一个功能,ImageTargets*,以及如何创建自己的图像目标并向其添加虚拟内容。你还学习了如何使用 Unity 界面和脚本来创建消息和按钮,以及顺序指令。
通过所有这些,你已经掌握了使用 Vuforia 创建可实施于安装、维护或培训流程的工业 AR 指南所需的技能。你还学会了如何使用 OpenURL 方法,其中包含 URL,通过它来定制步骤,甚至添加额外的 PDF 或视频和数据文件,这些文件可以是本地获取的(如本项目所示)或从远程服务器获取的。
现在,你可以利用这些知识来创建你自己的流程指南,并将当前项目作为模板。你也可以通过使用现实生活中的图片,将一些步骤链接到你的指令 PDF 文件,或者使用来自服务器的信号或信息触发从一步到另一步的变化来改进和扩展它。
正如你所见,该项目也易于在移动设备上部署,从这里,你可以尝试将其迁移到其他类型的眼镜上,看看结果。你也已经掌握了尝试其他 Vuforia 示例的技能,这些示例可以在 Unity Asset Store 中找到,由 PTC 发布:assetstore.unity.com/publishers/24484。
在下一章中,我们将完全改变范围,学习如何使用 ARKit 为旅游行业创建一个 AR 门户,将用户带入一个虚拟的 3D 世界。
第八章:使用 ARKit 进行旅游
本章中,我们将探索 ARKit,这是苹果公司自己的 AR SDK,它提供了许多功能,如空间跟踪、图像跟踪、协作 AR 等。我们还将学习如何利用世界跟踪来为旅游行业创造不同的 AR 体验。
本章的主要目标是向您介绍 ARKit 及其工作原理,通过在现实世界中搜索和跟踪平面表面。然后,您将学习如何使用这些功能在 AR 中放置元素并锚定它们,以创建一个三维门户,将用户引入一个三维世界。本章的第二个目标是展示一种不同的旅游观。您将学习如何利用 AR 创造独特体验,这些体验可以应用于博物馆、景观、兴趣点等。通过这样做,您将能够根据您的兴趣修改和应用此项目。
本章将涵盖以下主题:
-
使用 AR 进行旅游
-
探索 ARKit
-
开发 ARKit 应用程序
-
创建 AR 门户
技术要求
本章的技术要求如下:
-
一台运行 macOS Sierra 10.12.4 或更高版本的 Mac 电脑(本书中使用的是 Mac mini,Intel Core i5,4 GB 内存,运行 macOS Mojave)
-
Xcode 的最新版本(本书中为 10.3)
-
兼容 iOS 11+的 ARKit 兼容 iPhone/iPad(我们在 iPad Pro 10.5 上运行 iOS 13.1.1 进行了测试)
本章的代码文件和资源可以在以下链接找到:github.com/PacktPublishing/Enterprise-Augmented-Reality-Projects/tree/master/Chapter08
当我们探索 ARKit 时,我们将解释您根据想要使用的 ARKit 功能所需满足的设备要求,因为并非所有设备都能使用它们。
最后,请注意,本章专门针对 iOS 设备。因此,您需要一个 Apple 账户(免费或开发者账户)来在您的 iOS 设备上编译项目。您可以在以下链接中找到更多信息:developer.apple.com/support/compare-memberships/
使用 AR 进行旅游
AR 主要是一种视觉技术。尽管它可以结合其他效果,如声音以使体验更加真实,或者在我们玩游戏时在手机上产生震动,但其主要吸引力在于它在现实世界之上显示的视觉内容。这使得这项技术非常适合增强旅行体验,从展示天际线信息到使博物馆中的动物栩栩如生,甚至实时翻译标志和指南。
回到 2000 年代末/2010 年代初,当智能手机开始流行时,最早出现的 AR 应用之一就是以旅游为导向的。例如,2010 年,伦敦博物馆发布了一款 iPhone 应用,可以在真实地点上显示城市的历史照片。这个例子也被推广到其他城市和范围,如在西班牙纳瓦拉,用户可以通过指向放置在不同地点的板面,在 AR 中重新播放该地区不同地点拍摄的名场景。在这种情况下,移动设备使用图像识别(板面)来启动 AR 体验。然而,在 2010 年代初,最稳定和最广泛使用的 AR 技术是基于位置的,使用设备的 GPS、加速度计和指南针。Layar 和 Wikitude 等 AR 引擎和应用程序被广泛使用,因为它们允许开发者基于城市中的兴趣点(POI)生成路线、障碍赛和甚至游戏。
现在,AR 在旅游中最常见的应用如下:
-
作为新城市街道上的现场导游,用户可以在 AR 应用显示他们最感兴趣的景点位置的同时在城市中四处走动,通过使用箭头来指示。
-
在地图上展示景点和 POI。在这里,当用户用摄像头指向地图时,POI 会从地图上弹出,他们可以与之互动以获取更多信息。
-
提供关于画作、雕塑或纪念碑的额外信息。在这里,当用户指向一幅画作时,它可以显示关于艺术家以及画作创作地点和时间的视频,甚至可以将其以 3D 模拟的形式栩栩如生地呈现出来。
除了所有这些体验之外,当 AR 与其他沉浸式技术如虚拟世界或 360 度视频结合时,体验又向前迈出一步,使用户能够同时访问多个地方(例如,在博物馆网络中,在访问其中一个的同时,能够虚拟访问其他地方)。
在本章中,我们将学习如何使用苹果的 ARKit SDK 将这些体验混合在一起,以创建一个艺术体验。我们将创建一个 AR 门户,当用户通过它时,他们将降落在 3D 呈现的画作上。在我们的案例中,我们将使用从 Sketchfab 下载的梵高的画作(阿尔勒的卧室)来给用户一种仿佛置身于 3D 梵高画作中的错觉:sketchfab.com/3d-models/van-gogh-room-311d052a9f034ba8bce55a1a8296b6f9。
为了实现这一点,我们将创建一个面向旅游领域的应用程序,可以在博物馆、画廊等地方展示。关于我们将要使用的工具,在下一节中,我们将解释 ARKit 是如何工作的以及其主要功能。
探索 ARKit
苹果在 2017 年与 Xcode 9 和 iOS 11 一起发布了 ARKit 的第一个版本,将 AR 引入 iOS 设备。该框架包含在 Xcode 中,为开发者提供了在他们的应用程序或游戏中创建 AR 体验的可能性,这些软件结合了 iOS 设备的运动特性和相机追踪功能。它允许用户在现实世界中放置虚拟内容。在官方发布几个月后,它增加了新功能,如 2D 图像检测和面部检测。iOS 11 及以上版本可用的主要功能如下:
-
在物理环境中追踪和可视化平面(iOS 11.3+),例如桌子或地面
-
在现实世界中追踪已知的 2D 图像(iOS 11.3+),并在其上放置 AR 内容(图像识别)
-
在相机流中追踪面部(iOS 11.0+),并在其上叠加虚拟内容(例如,虚拟头像面部),这些内容会实时对面部表情做出反应
除了这些功能之外,AR 体验还可以通过使用附加到虚拟对象上的音效或集成其他框架(如视觉框架)来增强,以向应用程序添加计算机视觉算法,或者使用 Core ML 来添加机器学习模型。
2018 年,随着 iOS 12 的发布,ARKit 2 推出了新功能:
-
3D 物体追踪,其中真实世界中的物体是触发 AR 元素的那些
-
多用户 AR 体验,允许彼此靠近的用户共享相同的 AR 环境
-
为 AR 对象添加逼真的反射,以使体验更加真实
-
保存世界映射数据,以便当用户在现实世界中放置虚拟元素时,下次应用程序重新启动,虚拟元素将出现在相同的位置
在撰写本书时,iOS 13 与 ARKit 3 刚刚发布,并承诺对当前状态有巨大的改进,因为它增加了一种与虚拟元素交互的新方式,例如当检测到有人站在它们前面时隐藏虚拟对象。它还允许用户通过手势与 3D 物体交互,并捕捉到人的面部表情和动作。
由于每次 iOS 启动时都会进行更改,因此我们在这里提到的并非所有功能都适用于所有设备。在 developer.apple.com/documentation/arkit 的开发者页面上列出了当前的 ARKit 功能以及开发测试所需的最小 Xcode 和 iOS 版本。
对于这个项目,我们将使用平面检测,这是一个可以在 iOS 11 及以上版本上运行的基本功能。我们将在下一节中探讨这一点。
开发 ARKit 应用程序
要开始使用 ARKit 开发应用程序,请确保您拥有我们在 技术要求 部分中讨论的所需硬件,包括 iOS 设备,因为运行应用程序是必要的。
您还需要一个 Apple 账户才能在真实设备上构建项目。如果您没有付费账户,您也可以使用您的常规免费 Apple ID 登录。使用免费账户时的当前限制如下:同一时间在您的设备上安装最多三个应用程序,并且每七天可以创建最多 10 个不同的应用程序。
在本节中,我们将使用 Xcode 的模板创建一个 AR 项目,并介绍其主要组件。然后,我们将修改基本应用程序以可视化检测到的表面并向用户显示重要信息。
创建新的 AR 项目
让我们使用 ARKit 创建一个新的增强现实应用程序。我们将通过以下步骤在 Xcode 中创建项目,Xcode 是 macOS 的开发者工具集,我们可以从 Mac App Store 免费下载:
- 创建一个新项目,选择增强现实应用程序,然后点击“下一步”。这将为我们提供一个基本框架,以便我们可以开始使用 AR:

选择增强现实应用程序模板
- 填写产品名称、团队(在这里,您必须输入您的 Apple ID,尽管您可以将它留为“无”(如下面的截图所示),但您稍后必须填写它以将项目部署到设备上),以及组织名称:

填写我们项目的核心值
-
点击“下一步”,选择项目位置,然后点击“创建”。
-
如果您在 步骤 2 中没有输入您的开发者 ID,则项目的签名选项卡的一般窗口将显示错误,这将阻止应用程序在设备上构建,如下面的截图所示。现在修复它以便能够运行应用程序:

当未选择团队时,项目的签名选项卡会显示错误
- 我们已经有一个可以执行的应用程序。要测试它,连接您的设备,并从窗口的左上角选择它,如下面的截图所示:

选择运行应用程序的设备
- 通过点击窗口左上角的播放按钮来运行应用。第一次启动时,它会请求摄像头的权限,一旦摄像头流出现,它就会将一艘宇宙飞船锚定在你的环境中间:

船只看起来锚定在真实环境中
- 由于 ARKit 将会跟踪你的环境,请尝试移动船只并靠近它或从不同的角度观察它,如下面的截图所示:

现在,让我们看看构成这个项目的主体部分,即 Main.storyboard,其中包含 UI 元素,以及 ViewController.swift,其中包含应用的逻辑。
Main.storyboard
通过点击它打开 Main.storyboard 文件。此文件包含 UI 元素。目前,它只包含一个 ARSCNView,占据了整个屏幕。
如果你右键单击场景视图,你会看到与场景视图变量链接的引用出口,如下面的截图所示:

UI 元素 ScenView 及其引用的出口
让我们更仔细地看看视图控制器元素。
ViewController.swift
现在,点击 ViewController.swift,这是我们应用的主要逻辑所在。
你首先会看到,该类需要 ARKit 库进行 AR,UIKit 库进行界面,以及 SceneKit 库。最后一个是一个高级 3D 框架,苹果提供它,以便你可以创建、导入和操作 3D 对象和场景。我们将在本章后面使用它来将我们的外部 3D 模型导入场景。
我们目前唯一的变量如下:
@IBOUtlet var sceneView: ARSCNView!
这是来自 Main.storyboard 的 ARSCNView 元素。它将允许我们控制 AR 场景。
我们的 ViewController 类继承自 UIViewController。从这里,我们有三个 override 方法。第一个是 viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
sceneView.delegate = self
sceneView.showsStatistics = true
let scene = SCNScene(named: "art.scnassets/ship.scn")!
sceneView.scene = scene
}
当视图加载到内存中时,会调用此方法,并用于初始化元素。在这种情况下,我们将 sceneView 元素的代理附加到类本身,激活将在应用底部显示的统计信息,创建一个带有船只模型的场景,并将该场景分配给 scenView 元素。这将使战舰在应用启动时立即出现。
第二个方法是 viewWillAppear:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let configuration = ARWorldTrackingConfiguration()
sceneView.session.run(configuration)
}
当设备准备好向用户显示界面时,会调用此方法。AR 会话从这里启动。ARSession 是控制 AR 体验的主要元素;它从你的设备传感器读取数据,控制设备的摄像头,并分析从它传来的图像,以在放置 AR 对象的真实世界和虚拟空间之间创建对应关系。
在运行会话之前,我们需要使用ARConfiguration类,该类将确定会话中启用的 ARKit 功能。在这种情况下,它将使用设备的后置摄像头跟踪设备相对于表面、人物、图像或对象的位置和方向,然后使用该配置运行会话。如果我们只想跟踪人们的面孔或只想跟踪图像,我们可以使用不同的配置。(有关更多信息,请参阅developer.apple.com/documentation/arkit/arconfiguration。)
第三个重写方法是viewWillDisappear:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
sceneView.session.pause()
}
当视图即将被移除时,会调用此方法。当这种情况发生时,视图的会话将被暂停。
这些是目前我们实现的方法。现在,我们将开始更改和添加代码,以了解 ARKit 如何跟踪平面以及了解不同的状态变化。
修改基本应用
从ViewController.swift中的当前代码开始,我们将对其进行修改,使其只检测水平表面(不是垂直面、面或已知图像),并在检测过程中显示这些水平表面,以显示有关ARSession的额外信息,例如当ARTracking准备就绪或检测到新的水平表面时。
在我们进行这个操作之前,我们将删除船模型,因为我们不再需要它。按照以下步骤删除船模型:
-
从项目中删除
art.scnassets文件夹。 -
在
ViewController.swift的viewDidLoad()方法中,从场景中删除对船的引用,使scene行如下所示:
let scene = SCNScene()
我们还将启用一个 AR 调试选项,这将使我们能够看到我们环境的特征点。正如我们在这本书中已经看到的,特征点是图像的独特点,使得该图像可以被识别和跟踪。特征点越多,跟踪就越稳定。我们现在将激活此选项,以便我们可以看到我们的环境检测得有多好,并在我们的最终应用中将其禁用。为此,在viewDidLoad()方法中,在sceneView.showStatistics = true行之后,添加以下代码:
sceneView.debugOptions = ARSCNDebugOptions.showFeaturePoints
然后,我们可以继续进行平面检测。
检测并显示水平平面
如我们之前提到的,ARSession是 AR 应用的主要元素。ARKit 的另一个基本元素是ARAnchor,它是现实世界中一个有趣点的表示,包括其位置和方向。我们可以使用锚点在现实世界中放置和跟踪与相机相关的虚拟元素。当我们将这些锚点添加到会话中时,ARKit 会优化该锚点周围的全球跟踪精度,这意味着我们可以像它们被放置在现实世界中一样在虚拟对象周围行走。
除了手动添加锚点之外,一些 ARKit 功能可以自动将它们自己的特殊锚点添加到会话中。例如,当我们激活 ARConfiguration 类中的平面检测功能时,每当检测到新的平面时,就会自动创建 ARPlaneAnchor 元素。
让我们使这些平面锚点可见,这样我们就可以看到 ARKit 的工作原理。让我们开始吧:
- 在
viewWillAppear方法中,在configuration定义之后,添加以下代码:
let configuration = ARWorldTrackingConfiguration()
configuration.planeDetection = .horizontal
现在,ARKit 将只寻找水平表面进行跟踪。
- 取消注释类中已经存在的
renderer方法:
func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
let node = SCNNode()
return node
}
当场景中添加新的 ARAnchor 时,会调用此方法。它帮助我们为该锚点创建一个名为 SCNNode 的 SceneKit 节点。
- 现在,为了绘制平面,在节点创建和
return语句之间添加以下代码:
guard let planeAnchor = anchor as? ARPlaneAnchor else {return nil}
let plane = SCNPlane(width: CGFloat(planeAnchor.extent.x), height: CGFloat(planeAnchor.extent.z))
plane.firstMaterial?.diffuse.contents = UIColor.orange
plane.firstMaterial?.transparency = 0.4
let planeNode = SCNNode(geometry: plane)
planeNode.position = SCNVector3(x: planeAnchor.center.x, y: planeAnchor.center.y, z: planeAnchor.center.z)
planeNode.eulerAngles.x = -Float.pi/2
node.addChildNode(planeNode)
在这里,如果我们的锚点是一个 ARPlaneAnchor,我们创建一个新的半透明的橙色平面,其大小与 planeAnchor 相同。然后,我们创建一个带有该平面的 SCNNode 并将其添加到已经创建的空节点中。最后,我们返回这个父节点,以便它与我们的当前锚点相关联并在场景中显示。
除了这种方法,我们还可以从 ARSCNViewDelegate 实现另一种方法:func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor){}。在这里,空节点已经创建好了,所以我们只需要添加相同的先前代码片段。
- 如果你现在测试这个应用,你会看到每当它检测到平坦表面时,它会如何绘制橙色平面。然而,你会看到一旦一个平面被绘制,即使 ARKit 检测到更多围绕它的点,平面的尺寸也不会更新,如下面的截图所示:

ARKit 检测平坦表面并放置平面
让我们添加一些代码,以便在检测到更多点时,显示的平面会改变其大小和位置。
- 在类的开头,在
sceneView之后创建一个数组来保存场景中的所有平面及其相应的锚点:
var planes = [ARPlaneAnchor: SCNPlane]()
- 现在,在
renderer方法中,在创建平面之后,并在return语句之前,添加以下代码:
planes[planeAnchor] = plane
这将保存我们的平面节点和锚点以供以后使用。
- 让我们添加一个新的方法:
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor)
{
guard let planeAnchor = anchor as? ARPlaneAnchor else {return}
if let plane = planes[planeAnchor]
{
plane.width = CGFloat(planeAnchor.extent.x)
plane.height = CGFloat(planeAnchor.extent.z)
node.childNodes.first?.position = SCNVector3(planeAnchor.center.x, planeAnchor.center.y, planeAnchor.center.z)
}
}
当锚点更新时,会调用此方法。首先,我们检查锚点是否为 ARPlaneAnchor。然后,我们从数组中取出与该锚点对应的平面,并更改其 width 和 height。最后,我们更新 child 节点的 position(记住我们添加了我们的平面节点到一个空节点中;我们想要更新平面的位置,而不是空节点位置)。
- 运行应用以查看当你移动设备时,平面会变得越来越大:

当 ARKit 检测到更多点时,检测到的平面会变得更大
在本节中,我们学习了如何创建平面锚点以及如何可视化它们。
在测试应用时,你可能已经注意到设备需要一点时间才开始显示平面的锚点。这是 ARKit 初始化的时间。在下一节中,我们将创建一个 ARKit 状态变化的跟踪,以便用户知道应用何时准备就绪。
将 ARSessionDelegate 添加以跟踪状态变化
在我们的类中,我们已经有三个方法可以用来在会话失败或中断时通知用户会话变化。我们还将添加两个新方法,即当锚点添加到会话中以及当相机改变其跟踪状态时。但在我们做任何这些之前,我们需要在我们的 UI 中创建一个标签来显示所有消息。
添加标签 UI 元素
让我们添加一个新的 UI 元素,即标签,以向用户显示通知。为此,请按照以下步骤操作:
- 打开
Main.storyboard,并打开屏幕右上角的库按钮(其集合中的第一个按钮,内部有一个正方形在圆圈中):

图书馆按钮
- 在视图中查找并拖动一个标签:

从库中选择标签
-
在选择标签后,使用Ctrl + 鼠标拖动为标签创建关于视图的约束,或者在工具栏中点击位于手机视图下方的添加新约束按钮。约束帮助我们固定屏幕上的元素,以便它们在任何设备屏幕和任何方向上都能正确显示。
-
然后,将左侧、右侧和底部约束的值分别修改为
20、20和0(约束的图标将变为鲜红色)。勾选高度约束框并将其设置为60,如下所示:

为标签添加约束
- 新的约束将出现在右侧窗口的“显示大小检查器”选项卡下,如下所示:

在“显示大小”选项卡底部添加的四个新约束
- 在“显示属性检查器”选项卡中,删除默认文本,将标签颜色设置为绿色,勾选动态类型复选框,并将文本对齐设置为居中,如下所示:

修改标签的属性
- 要将标签连接到我们的
ViewController.swift脚本并在我们的方法中使用它,请点击右上角的“显示辅助编辑器”按钮(两个圆圈相交)以打开脚本:

选择辅助编辑器
- 按Ctrl并拖动标签(当你拖动鼠标时,你会看到一个蓝色线条),从层次视图拖动到代码,在
sceneView变量下方。释放鼠标。然后,在以下截图所示的弹出窗口中,输入变量的名称,在本例中将是infoLabel,然后点击连接:

UI 中的标签将附加到 infoLabel 变量
- 打开
ViewController.swift文件以检查新变量是否已正确添加,如下所示:
@IBOutlet weak var infoLabel: UILabel!
现在,我们可以通过界面开始向用户发送消息。
向用户发送通知
现在我们有了用于向用户显示消息的标签,让我们使用 ViewController 类中已有的 session 方法,并创建新的方法来显示有用的信息,如下步骤所示:
- 在
ViewController.swift文件中,在didFailWithError会话内,添加一条新信息:
func session(_ session: ARSession, didFailWithError error: Error) {
infoLabel.text = "Session failed : \(error.localizedDescription)."
}
当 ARSession 中出现错误时,将显示此消息。
- 在
sessionWasInterrupted方法中,添加以下信息:
func sessionWasInterrupted(_ session: ARSession) {
infoLabel.text = "Session was interrupted."
}
这将在会话中断时执行;例如,当应用最小化时。
- 在
sessioInterruptionEnded方法中,添加以下信息和代码:
func sessionInterruptionEnded(_ session: ARSession) {
infoLabel.text = "Session interruption ended."
let configuration = ARWorldTrackingConfiguration()
configuration.planeDetection = .horizontal
sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
}
当会话中断完成时,我们必须重置跟踪。为此,我们将再次创建配置参数并通过移除之前存在的锚点来运行会话。
- 现在,让我们创建一个新的方法,用于检测跟踪状态何时发生变化:
func session(_ session: ARSession, cameraDidChangeTrackingState camera: ARCamera) {
let message: String
switch camera.trackingState {
case .normal where session.currentFrame!.anchors.isEmpty:
message = "Move the device around to detect horizontal surfaces."
case .notAvailable:
message = "Tracking unavailable."
case .limited(.excessiveMotion):
message = "Tracking limited - Move the device more slowly."
case .limited(.insufficientFeatures):
message = "Tracking limited - Point the device at an area with visible surface detail, or improve lighting conditions."
case .limited(.initializing):
message = "Initializing AR session."
default:
message = ""
}
infoLabel.text = message
}
您的 Xcode 窗口将如下截图所示:

ViewController 中的新方法
此方法检查跟踪状态,并在会话初始化或存在问题时显示消息。我们还在跟踪状态正常但尚未找到平面锚点时显示消息,因此用户需要继续四处张望。
- 现在,我们必须在添加锚点时通知用户,这样他们就不必再四处张望了。为此,我们将使用
ARSessionDelegateProtocol。我们首先将要做的是将代理添加到类中,如下代码所示:
class ViewController: UIViewController, ARSCNViewDelegate, ARSessionDelegate {
类声明将如下所示:

添加了代理的 ViewController 类
- 在
viewWillAppear方法中,在sceneView.session.run(configuration)行之后,添加以下代码:
sceneView.session.delegate = self
通过这一行,我们将代理分配给类。viewWillAppear 方法现在将如下所示:

viewWillAppear 方法
- 现在,创建一个新的方法来显示添加锚点时的消息:
func session(_ session: ARSession, didAdd anchors: [ARAnchor])
{
infoLabel.text= "New anchor added."
}
- 运行应用以查看标签如何根据摄像头的状态变化,如下所示:

通知用户 AR 会话正在初始化的标签
在 AR 初始化后,标签将变为检测水平表面的信息,如下截图所示:

询问用户将设备移动以检测水平表面的标签
cameraDidChangeTrackingState会话方法的调试信息来自跟踪和可视化平面示例,该示例可在developer.apple.com/documentation/arkit/tracking_and_visualizing_planes找到。此示例项目使用了更多方法来显示平面和消息,而我们在这个项目中不需要它们。如果您想了解它们,可以下载并测试。
现在我们有了我们 app 的基础,让我们创建一个 AR 门户,我们将在这里展示一个通向虚拟 3D 画作的门。一旦我们物理上穿过那扇门,我们就会发现自己沉浸在那个虚拟画作中。
创建一个 AR 门户
目前,我们有一个检测水平平面并通知我们跟踪系统状态的 app。现在,我们想要创建一个 AR 体验,其中用户将触摸屏幕来创建一个门户,并且通过它时,可以看到自己身处梵高的阿尔勒的卧室画作的三维表示。以下图显示了 SceneKit 坐标系中的场景:

XYZ 坐标中的场景
从用户的视角来看,我们将有一个带有孔的门户,如图中所示。这个孔将让我们看到背景中的模型,即 3D 画作。门户不会是灰色的;它将是透明的,这样我们就可以看到摄像头传输的内容,而不是隐藏在它后面的整个 3D 画作场景。在本节中,我们将学习如何实现这一点。
为了做到这一点,我们需要添加 3D 模型,创建屏幕触摸功能,并创建实际的门户,它只从外面显示画作的局部。
从现在开始,您可以指定是否要显示特征点选项以及显示平面的两个renderer方法。我们将把它们留到项目结束时,因为最好是在我们首先理解 ARKit 的工作原理之后再进行这些操作。
在以下子节中,我们将做以下事情:
-
将 3D 模型导入我们的项目和场景
-
添加用户交互,以便当用户触摸屏幕时,3D 模型将出现在被触摸的锚平面之上
-
将墙壁添加到门户中,使模型从外面不可见,除了门
-
通过给墙壁添加纹理和指南针图像来改进应用,以帮助用户找到门户出现的位置
现在,让我们先添加我们想要展示的 3D 模型。
导入 3D 模型
SceneKit 首选的 3D 模型类型是 Collada(.dae 文件)。然而,它也可以读取 OBJ(.obj)文件,在这种情况下,下载的模型是后一种格式。我们使用 3D 建模程序对其进行略微修改,并将基点放在离我们最近的边缘的地板上。这样,当我们将其放置在现实世界中时,我们将看到模型在我们面前,而不是围绕我们。如果您尝试使用其他模型或不知道如何修改基点,您可以直接在代码中调整变换的位置(我们稍后会解释)。
将模型添加到项目中
要导入模型并在我们的场景中显示它,请从本项目的资源中下载它并遵循以下步骤:
- 右键点击项目并选择新建组,如下截图所示。命名为
Models:

创建一个新组来包含我们的模型
- 右键点击
Models文件夹,选择将文件添加到“ARPortal”…,如下所示:

将文件添加到我们的文件夹中
- 导航到包含模型、材质和纹理的
vangogh_room文件夹。选择它,确保它已添加到我们的应用中,并点击添加,如下截图所示:

选择文件夹并将其添加到目标应用中
- 如果您展开
vangogh_room文件夹,您将看到其中的所有文件。点击vangogh_room.obj文件在屏幕上可视化 3D 模型。当我们创建门户时,我们将从开放的墙壁进入模型,如下截图所示:

在 3D 中显示的.obj 文件
现在,我们可以在我们的代码中使用我们的模型。
将模型添加到我们的场景中
现在我们已经将模型导入到我们的项目中,让我们使用以下代码将其添加到我们的场景中:
- 通过右键点击
ARPortal文件夹并选择新建文件…来创建一个新文件,如下所示:

创建新文件
- 选择 Swift 文件并点击下一步:

选择 Swift 文件
-
命名为
Portal.swift并点击创建。这将是我们创建完整门户的类,包括我们之前导入的 3D 模型。 -
删除代码并添加
ARKit库:
import ARKit
- 创建一个
class:
class Portal: SCNNode {
}
我们的门户将是SCNNode类型。
- 现在,在类内部,我们将创建一个新的方法来加载 3D 模型。添加以下代码:
func add3DModel() {
let modelScene = SCNScene(named: "vangogh_room.obj")!
let modelNode: SCNNode = modelScene.rootNode.childNodes[0]
self.addChildNode(modelNode)
}
在这里,我们从.obj文件中加载场景并从中提取节点。然后,我们将节点作为我们的门户的子节点附加。
如果你使用另一个模型并且它没有出现在你想要的位置(在一个或多个轴上偏移),你可以在self.addChildNode(modelNode)行之前添加以下内容来调整其位置:modelNode.position = SCNVector3(x: YourValue, y: YourValue, z: YourValue)。你可以通过查看本节开头的图解来检查 SceneKit 中的坐标如何工作。
- 现在,按照如下方式
重写``init方法:
override init() {
super.init()
add3DModel()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
在第一个方法中,我们通过添加 3D 模型来初始化我们的传送门。第二个方法是SCNNode子类所必需的。
现在我们已经添加了我们的 3D 模型,我们想在场景中显示它。
我们可以直接打开ViewController.swift文件,并在viewDidLoad()方法的末尾添加以下内容,如下所示:
portal = Portal()
self.sceneView.scene.rootNode.addChildNode(portal!)
viewDidLoad方法现在将如下所示:

添加传送门后的viewDidLoad方法
在这种情况下,3D 模型将像我们在本章开头看到的船一样出现,从会话开始到屏幕中间(我们可能需要向下翻译以获得更好的视角)。然而,我们想要添加一个转折,并在用户触摸屏幕时将其附加到其中一个平面锚点上,因此删除这两行。我们将在下一节中学习如何做到这一点。
包括用户交互
让我们给应用添加一些用户交互。而不是一开始就使虚拟内容出现在场景中,我们将使其在用户触摸屏幕时出现。为此,请按照以下步骤操作:
- 在
Main.storyboard中,点击库按钮(圆圈内的正方形按钮)并查找触摸手势识别器。将其拖到视图中:

从库中选择触摸手势识别器
- 它将显示在以下截图所示的层次结构中:

在视图控制器场景层次结构中点击“触摸手势识别器”
- 显示辅助编辑器(两个相交的圆圈按钮)并在右侧打开
ViewController.swift。Ctrl + 将触摸手势识别器拖到代码中,如下所示:

将触摸手势识别器拖到代码中以创建连接
- 在出现的框中填写以下参数:
-
连接:
Action -
对象:
视图控制器 -
名称:
didTapOnScreen -
类型:
UITapGestureRecognizer
- 打开
ViewController.swift文件以确保已创建该方法:
@IBAction func didTapOnScreen(_ sender: UITapGestureRecognizer){
}
- 现在,在类开始处,在
planes变量之后包含以下变量:
var portal: SCNNode? = nil
我们将使用这个变量来确保视图中只有一个传送门。
- 修改会话的
didAdd方法中的文本,指示用户在检测到锚点但尚未添加传送门时放置传送门。为此,修改infoLabel.text,如下所示:
func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {
if portal == nil
{
infoLabel.text = "Tap on the floor to create the portal."
}
}
- 现在,前往
didTapOnScreen方法并添加以下代码:
let location = sender.location(in: sceneView)
let hitResults = sceneView.hitTest(location, types: ARHitTestResult.ResultType.existingPlaneUsingExtent)
guard let result = hitResults.first else {return}
if portal != nil {
portal?.removeFromParentNode()
}
portal = Portal()
portal?.position = SCNVector3(x: result.worldTransform.columns.3.x, y: result.worldTransform.columns.3.y, z: result.worldTransform.columns.3.z)
self.sceneView.scene.rootNode.addChildNode(portal!)
infoLabel.text = ""
在这里,我们取出点击的位置并检查点击是否击中了一个现有的平面。(您可以在ARHitTestResult的选项中检查:developer.apple.com/documentation/arkit/arhittestresult。)我们取击中结果中的第一个平面。如果传送门已经存在,我们将删除它以确保我们只有一个传送门在视图中。如果用户在屏幕的不同位置点击,传送门将看起来从一个地方移动到另一个地方。然后,我们将平面的位置应用到我们的传送门对象上。最后,我们将传送门添加到我们的场景中,并且我们将清除信息标签,因为我们不再需要告诉用户点击屏幕。结果的方法将如下所示:

didTapOnScreen方法
- 在
sessionWasInterrupted方法中,在infoLabel.text之后,我们将删除传送门,以确保在会话恢复时它不会出现。为此,添加以下代码:
func sessionWasInterrupted(_ session: ARSession) {
infoLabel.text = "Session was interrupted."
portal?.removeFromParentNode()
portal = nil
}
sessionWasInterrupted方法应如下所示:

sessionWasInterrupted方法
- 运行应用并点击屏幕以放置 3D 模型。它将出现在橙色平面上,如下面的截图所示:

当在屏幕上点击时出现在 AR 中的 3D 绘画
如果你进入模型并回头看,你将看到从 3D 模型中开放的墙壁看到的现实世界,如下面的截图所示:

从 3D 房间到现实世界的开口
在房间内四处走动,从不同的角度探索 3D 空间。你会看到你沉浸在虚拟环境中,而现实世界仍然在另一边。
现在,是时候真正创建一个隐藏模型大部分直到门被穿越的传送门了。为此,我们将创建透明墙壁并玩渲染顺序属性。
添加传送门的墙壁
AR 传送门的主要技巧基于两个东西:透明度和渲染顺序。我们将创建一个带有中间开口(我们将称之为门)的墙壁,通过这个开口我们将看到 3D 绘画。打开Portal.swift文件并按照以下步骤操作:
- 创建一个名为
createWall的新方法,代码如下:
func createWall(width: CGFloat, height: CGFloat, length: CGFloat)->SCNNode {
let node = SCNNode()
let wall = SCNBox(width: width, height: height, length: length, chamferRadius: 0)
wall.firstMaterial?.diffuse.contents = UIColor.white
let wallNode = SCNNode(geometry: wall)
node.addChildNode(wallNode)
return node
}
在这里,我们创建了一个父节点。然后,我们创建了一个给定大小的盒子,并将其材质设置为白色。我们创建了一个具有盒子几何形状的节点,并将其附加到父节点上,然后返回它。这将是我们创建传送门墙壁的基础:

新的createWall方法
- 让我们创建另一个名为
createPortal的方法:
func createPortal() {
}
- 在内部,让我们定义墙壁大小的变量。添加以下代码:
let wallWidth: CGFloat = 2
let doorWidth: CGFloat = 0.8
let topWidth = 2 * wallWidth + doorWidth
let height: CGFloat = 2
let length: CGFloat = 0.05
我们将会有四面墙壁,即在传送门门的左侧、右侧、顶部和底部。前三个必须足够大,以隐藏模型不被显示在传送门后面。它们的长度将是唯一显示的东西(从而模拟通往另一个维度的门)。底部墙壁将关闭那个开口。
- 现在,使用之前的方法
createWall创建主节点和四面墙壁:
let portal = SCNNode()
let leftWall = createWall(width: wallWidth, height: height, length: length)
leftWall.position = SCNVector3(x: Float(-(wallWidth + doorWidth)/2), y: Float(height/2), z: 0)
let rightWall = createWall(width: wallWidth, height: height, length: length)
rightWall.position = SCNVector3(x: Float((wallWidth + doorWidth)/2), y: Float(height/2), z: 0)
let topWall = createWall(width: topWidth, height: height, length: length)
topWall.position = SCNVector3(x: 0, y: Float(height*3/2), z: 0)
let bottomWall = createWall(width: topWidth, height: length, length: length)
bottomWall.position = SCNVector3(x: 0, y: Float(-length/2), z: 0)
- 将墙壁添加到传送门节点,然后将传送门本身添加到类的节点,如下所示代码:
portal.addChildNode(leftWall)
portal.addChildNode(rightWall)
portal.addChildNode(topWall)
portal.addChildNode(bottomWall)
self.addChildNode(portal)
我们的 3D 传送门已经准备好了。你的代码应该如下所示:

createPortal方法
- 现在,让我们从
init中调用这个方法。在添加 3D 模型后,添加以下代码:
createPortal()
- 如果我们运行应用程序,当我们点击地板时,我们会看到一个白色的墙壁,通过它的缝隙,我们可以看到 3D 模型。当我们穿过它时,我们会发现自己身处 3D 画作中,如下面的截图所示:

覆盖大部分 3D 画作的白色墙壁
我们也可以让墙壁变得可见,这样我们就可以回到现实世界:

3D 画作内部的视图
- 然而,从外面看,我们不想看到一个白色的墙壁;传送门应该只是空气中的一个开口(墙上的缝隙)。为了达到这种效果,在调用
return node之前,让我们在createWall方法中添加另一个盒子。添加以下代码:
let maskedWall = SCNBox(width: width, height: height, length: length, chamferRadius: 0)
maskedWall.firstMaterial?.diffuse.contents = UIColor.white
maskedWall.firstMaterial?.transparency = 0.000000001
let maskedWallNode = SCNNode(geometry: maskedWall)
maskedWallNode.position = SCNVector3.init(0, 0, length)
node.addChildNode(maskedWallNode)
这个新墙壁位于另一个墙壁之前,其透明度接近 0(如果设置为0,则被涂成黑色),这样我们就可以看到背景。但仅此还不够。
- 将
wallNode的渲染顺序设置为100,将maskedWallNode的渲染顺序设置为10,但将createWall方法的最终代码保持如下:
func createWall(width: CGFloat, height: CGFloat, length:
CGFloat)->SCNNode {
...
wallNode.renderingOrder = 100
node.addChildNode(wallNode)
...
maskedWallNode.renderingOrder = 10
node.addChildNode(maskedWallNode)
return node
}
createWall方法现在应该看起来如下:

最终代码的createWall方法
- 为了完成这个,给我们在
add3DModel方法中创建的modelNode添加一个渲染顺序200:
func add3DModel() {
...
modelNode.renderingOrder = 200
self.addChildNode(modelNode)
}
渲染顺序越低,物体在场景中的渲染速度越快。这意味着我们将首先看到maskedWallNode,然后是wallNode,最后是modelNode。这样,每当遮挡墙在视图中时,其表面后面的 3D 元素将不会被渲染,留下一个透明的表面,直接显示摄像头画面。唯一会被渲染的 3D 画作部分是未被墙壁覆盖的部分,即我们的传送门门。一旦我们穿过传送门,我们将看到完整的 3D 画作,当我们回头看时,我们将看到我们的白色墙壁。
- 运行应用程序,通过触摸屏幕来查看传送门是如何出现的。在下面的截图中,我们可以看到遮挡墙如何显示摄像头画面,隐藏其他元素。在这里,我们只能看到墙壁的开口(因为我们已经将其放置在遮挡墙的z轴后面)和通过开口的画作:
你可以在showFeaturePoints行和renderer方法上添加注释,这样特征点和锚平面就不会干扰我们的 3D 场景。

出现在 AR 中的门户
一旦进入绘画,如果我们回头,我们仍然会看到白色的墙壁和通往现实世界的出口,就像之前一样。
现在场景已经准备好了,让我们通过给墙壁添加一些纹理来改进它。
改进门户
我们将通过给墙壁添加一些纹理和一个将显示门户出现位置的指南针图像来改进我们的门户。为此,我们必须将纹理图像和指南针图像添加到我们的项目中。要这样做,请按照以下步骤操作:
- 右键点击 ARPortal 项目,选择“新建文件...”在此情况下,从资源选项卡中选择 SceneKit 目录,如图所示:

选择新的 SceneKit 目录
- 将其命名为
Media.scnassets并创建它,如下所示:

SceneKit 目录已成功创建
-
右键点击新创建的
Media.scnassets,选择“将文件添加到'Media.scnassets'...”。现在,从本项目的资源中选择wood.jpg图像并接受它。我们的图像已准备好使用。 -
用
compass.png图像重复步骤 3。 -
打开
Portal.swift,在createWall方法中找到以下行:
wall.firstMaterial?.diffuse.contents = UIColor.white
将其修改为如下所示:
wall.firstMaterial?.diffuse.contents = UIImage(named: "Media.scnassets/wood.jpg")
在这里,我们已将木质纹理添加到我们的门户中。
- 现在,我们将在
ViewController.swift中绘制指南针。为此,在门户变量之后创建以下变量:
var compass: SCNNode? = nil
- 现在,取消注释第一个
renderer方法,这是添加锚平面的地方(如果你已经注释了它),并用以下代码替换其中的代码:
if portal == nil && compass == nil
{
let node = SCNNode()
guard let planeAnchor = anchor as? ARPlaneAnchor else {return nil}
let plane = SCNPlane(width: 0.8, height: 0.8)
plane.firstMaterial?.diffuse.contents = UIImage(named: "Media.scnassets/compass.png")
plane.firstMaterial?.transparency = 0.8
let planeNode = SCNNode(geometry: plane)
planeNode.position = SCNVector3(x: planeAnchor.center.x, y: planeAnchor.center.y, z: planeAnchor.center.z)
planeNode.eulerAngles.x = -Float.pi/2
node.addChildNode(planeNode)
planes[planeAnchor] = plane
compass = node
return node
}
return nil
在这里,当检测到平面锚点时,如果没有门户或指南针在视图中(第一次检测到平面时),我们将绘制一个半透明的指南针,向用户显示未来门户的位置和方向。然后,我们将保存节点作为锚点,以便我们可以在步骤 9中使用它。
-
如果你还没有注释
didUpdate渲染方法,请现在注释它。我们以后不再需要它了。 -
在
didTapOnScreen方法中,删除portal = Portal()和self.sceneView.scene.rootNode.addChildNode(portal!)之间的代码,并替换为以下代码:
if (compass != nil)
{
portal?.position = compass!.position
portal?.rotation = compass!.rotation
compass?.removeFromParentNode()
compass = nil
}
else
{
portal?.position = SCNVector3(x: result.worldTransform.columns.3.x, y: result.worldTransform.columns.3.y, z: result.worldTransform.columns.3.z)
}
在这里,当用户第一次点击屏幕(指南针在视图中)时,我们使用指南针的位置和旋转放置门户,因为我们不再需要它,所以我们会删除指南针。从那时起,如果用户继续点击屏幕,门户将根据点击和锚平面位置移动,就像之前一样。
- 运行应用以查看设备检测到锚平面时指南针如何立即出现:

出现在屏幕上的指南针,指示未来门户的位置和方向
- 现在,轻触屏幕以查看门户有一个木制框架。这可以在以下屏幕截图中看到:

门户现在有一个木制框架
- 从内部看,墙壁的纹理也发生了变化,如下面的屏幕截图所示:

3D 绘画内部的视角
就这样。现在,你可以将门户放置在任何你想去的地方,并玩转不同的选项,比如更改 3D 绘画或同时创建多个门户。这取决于你!
摘要
在本章中,我们学习了什么是 ARKit 以及它是如何工作的。我们看到了相机如何识别特征点以及如何创建锚定平面,在这些平面上你可以放置虚拟元素。我们还学习了如何使用 SceneKit 将 3D 模型插入场景并操纵它们以创建一个 AR 门户,引导用户进入 3D 环境。
到现在为止,你应该已经掌握了基本技能,可以继续改进当前项目,并适应旅游行业或其他行业的个人需求。你可以尝试在界面中添加按钮来更改门户的 3D 内容,当门户首次出现时添加粒子效果,或者甚至尝试使用 360 度视频代替 3D 模型。AR 是一种跨领域的工具,可以用多种方式使用,并应用于许多不同的需求,因此你也可以为营销或零售等领域创建这个门户。
这是本书的最后一章,它致力于企业中 AR 的应用。到现在为止,你应该对 AR 如何在许多用途中发挥作用有一个更广泛的认识,包括旅游。现在,你需要做的就是开始尝试使用你所学到的不同框架和工具,并将它们适应到自己的需求和项目中。祝你好玩!
进一步阅读
如果你想要探索 ARKit,无论是为了推进当前项目还是尝试新事物,我们推荐查看苹果的示例项目,这些项目可以在 developer.apple.com/documentation/arkit 找到。以下是一些这些项目的例子:
-
提到的
developer.apple.com/documentation/arkit/tracking_and_visualizing_planes项目,你可以使用它来跟踪和可视化平面锚点 -
developer.apple.com/documentation/arkit/detecting_images_in_an_ar_experience项目,你可以使用它来检测 2D 图像(例如,门户可以出现在真实的画作上而不是街道中间) -
developer.apple.com/documentation/arkit/tracking_and_visualizing_faces项目,你可以使用它来跟踪面部并通过真实表情动画虚拟头像
随着 iOS 13 的发布,你可以尝试更多功能和项目,例如当人们站在虚拟物体前面时遮挡它们,或者通过手势与虚拟内容进行交互。





浙公网安备 33010602011771号