Unity 中的 QR 码

HoloLens 2 头戴显示设备可以跟踪和检测可用于提供全息影像和其他 AR 功能的 QR 码。 本文将指导你完成开始在 Unity 应用中开始使用 QR 码所需的一切,包括:

  • 将 QR 码检测添加到 Unity 应用。
  • 了解需要使用的重要概念和 Unity 组件。
  • 提供涵盖常见 QR 码用法的教程。
  • 介绍 AR 标记示例方案,演示启用了 QR 码的场景和示例脚本。

在继续本文之前,建议先浏览 QR 码概述

跟踪的 QR 码

配置 Unity 项目和应用

必须正确设置和配置 Unity 项目和应用才能启用 QR 码功能,这需要:

  • OpenXR for Windows 混合现实版本 113.2403.5001 或更高版本。

    注意

    这附带 OS,可通过 Windows 应用商店进行更新。 请注意,用户可能已安装早期版本,并且其设备将无法使用 AR 标记(如 QR 码),直到更新到版本 113.2403.5001 或更高版本。

  • 与受支持的 Unity 版本兼容的项目:
    • Unity 2022.3 LTS (建议)
    • Unity 2021.3 LTS
  • 混合现实 OpenXR 插件。
  • 为 Unity 项目启用的网络摄像头功能。
  • 授予应用的相机权限。

以下部分将指导你配置 Unity 项目和应用以启用 QR 码检测。

获取 混合现实 OpenXR 插件

混合现实 OpenXR 插件包包含可用于访问 QR 码功能的 C# API

导入包:

  1. 下载并运行混合现实功能工具。
  2. 安装 OpenXR 插件。

混合现实功能工具还简化了包管理,可用于查找、更新和添加应用所需的混合现实功能。 有关如何使用该工具的详细说明,请参阅欢迎使用 混合现实 功能工具

启用 WebCam 功能

若要检测和跟踪 QR 码,Unity 项目需要 启用 WebCam 功能。

启用 WebCam 功能:

  1. 打开 Unity 项目。
  2. 在 Unity 编辑器的应用菜单中单击“ 编辑 ”。
  3. 转到 “项目设置 > 播放器 ”并选择 “UWP ”选项卡,如下所示: UWP 选项卡设置
  4. “功能”列表中启用 WebCam已启用 WebCam 功能
  5. 退出 项目设置

现已为 Unity 应用启用 WebCam 功能。 但是,你的应用仍必须被授予访问设备相机的权限。

授予应用相机访问权限

如果应用启用了 WebCam 功能,权限对话框会提示用户授予应用对设备相机的访问权限。

“相机权限”对话框

此对话框仅向用户显示一次,通常在输入包含已启用 QR 码标记支持的场景ARMarkerManager时显示。 如果拒绝相机访问,用户可以转到“设置应用”>,并通过应用的高级选项启用它。

已启用权限的应用高级选项

将 QR 码检测构建到场景中

QR 码检测必须内置到想要在其中使用 QR 码的每个场景中,这需要:

为 QR 码创建 prefab

若要在场景中使用 QR 码,需要为 QR 码创建预制。 ARMarkerManager 使用此 prefab 在检测到 QR 码时创建一个 GameObject

若要为 QR 码创建 prefab,请执行:

  1. 为项目创建新的 prefab
  2. ARMarker组件添加到 prefab,位于 Script > Microsoft.MixedReality.OpenXR > ARMarker
    添加 ARMarker 组件

你现在有一个基本的 prefab 来处理。 你可能希望应用直观地表示环境中检测到的 QR 码。 下一部分将指导你如何添加 QR 码的视觉表示形式。

添加视觉对象

在上一部分中,添加到 ARMarkerprefab 也会自动添加 ARMarkerScale 组件。 此组件用于将 QR 码的视觉表示比例与其物理对应组件匹配。

为此,请执行以下操作:

  1. 将空 GameObject 添加到在上一节中创建的 prefab。 它将表示所有视觉 标记内容
  2. 将子 3D GameObject(如 a Quad)添加到标记内容 GameObject将 3D GameObject 添加到 ARMarker prefab
  3. 在 prefab 的ARMarkerScale组件中,将标记刻度转换设置为标记内容GameObject。 设置此字段可确保正确缩放所选的 3D GameObject ,以匹配实际 QR 码。

添加到 ARMarkerManager 场景

ARMarkerManager 只负责创建、更新和删除检测到的 QR 码的每一个 GameObject

若要添加到 ARMarkerManager 场景,

  1. 将一个 GameObject 放置到场景中。
  2. ARMarkerManager组件添加到GameObject位于 Script > Microsoft.MixedReality.OpenXR > ARMarkerManager 下的组件。
    添加 ARMarkerManager 组件
  3. ARMarkerManager“标记 Prefab”字段设置为在上一节中创建的 prefab。 标记 Prefab 字段集
  4. 展开 “启用标记类型”,然后选择一个元素并将其设置为 QR 码已启用 QR 码标记类型

跟踪 QR 码更改

ARMarkerManager 包含 markersChanged 向订阅者提供 ARMarkersChangedEventArgs 的事件。 使用这些事件参数跟踪在检测或更新的姿势数据中添加或删除了哪些 QR 码。

以下代码演示如何订阅 ARMarkerManager.markersChanged 事件,使用事件参数循环访问 ARMarker 对象 ARMarkerManager 正在处理和写入调试,无论它们是添加、删除还是更新。

using System;
using Microsoft.MixedReality.OpenXR;

// ...

private void Awake()
{
    m_arMarkerManager = GetComponent<ARMarkerManager>();
    m_arMarkerManager.markersChanged += OnQRCodesChanged;
}

void OnQRCodesChanged(ARMarkersChangedEventArgs args)
{
    foreach (ARMarker qrCode in args.added)
        Debug.Log($"QR code with the ID {qrCode.trackableId} added.");

    foreach (ARMarker qrCode in args.removed)
        Debug.Log($"QR code with the ID {qrCode.trackableId} removed.");

    foreach (ARMarker qrCode in args.updated)
    {
        Debug.Log($"QR code with the ID {qrCode.trackableId} updated.");
        Debug.Log($"Pos:{qrCode.transform.position} Rot:{qrCode.transform.rotation} Size:{qrCode.size}");
    }
}

获取上次检测到 QR 码的时间

使用该 ARMarker.lastSeenTime 属性来确定设备上次跟踪检测到的 QR 码的时间以及丢失跟踪的时间量(如果有)。 时间以自 Unity 启动应用程序以来的秒数进行度量,类似于 UnityEngine.Time.realtimeSinceStartup

使用 QR 码的可跟踪 ID

QR 码是 可跟踪的,这是 AR 设备可以在物理环境中检测和跟踪的任何内容。 可跟踪对象派生自提供 ID、跟踪状态、姿势和其他数据的类型 ARTrackable<TSessionRelativeData, TTrackable>

QR 码的可跟踪 ID 可以传递到 ARMarkerManager 方法中,以获取 QR 码的属性、原始字节数据和字符串表示形式,以及设置 QR 码的转换模式。 这些方法允许检索 QR 码的数据,而无需保留 ARMarker 对象引用。

可以将 QR 码的 ID 传递到以下 ARMarkerManager 方法中:

注意

GetRawData对于方法参数allocator,传递Unity.Collections.Allocator.Temp足以满足大多数方案。

遵循 QR 码的跟踪状态

由于可跟踪, ARMarker 因此它将继承属性 trackingState ,并设置为以下三 UnityEngine.XR.ARSubsystems.TrackingState个之一:

  • Limited:指示正在跟踪 QR 码,但信息有限,或者质量不佳。
  • Tracking:指定正在完全跟踪 QR 码。
  • None:指示未跟踪 QR 码。

若要监视 QR 码的跟踪状态,请 ARMarkerManager.markersChanged 订阅并循环访问 ARMarker 传递给事件处理程序的事件参数中提供的标记集合。

以下代码演示如何使用 ARMarkerManager.markersChanged 事件循环访问 ARMarker 新检测到的 QR 码的对象,并将其可跟踪 ID 写入“调试”窗口。

using System;
using Microsoft.MixedReality.OpenXR;

// ...

private void Awake()
{
    m_arMarkerManager = GetComponent<ARMarkerManager>();
    m_arMarkerManager.markersChanged += OnQRCodesChanged;
}

void OnQRCodesChanged(ARMarkersChangedEventArgs args)
{
    foreach (ARMarker qrCode in args.added)
    {
       if (qrCode.trackingState == UnityEngine.XR.ARSubsystems.TrackingState.Tracking)
           Debug.Log($"Fully tracked QR code with the ID {qrCode.trackableId} was added.");
    }
}

获取 QR 码的版本和 QR 码类型

获取检测到的 QR 码的版本和类型:

  1. 调用 ARMarker.GetQRCodeProperties(),返回实例 QRCodeProperties
  2. 访问返回值中的字段 QRCodeProperties 以获取 QR 码的类型。 该值为 QRCodeType.QRCodeQRCodeType.MicroQRCode
  3. 访问返回值的 QRCodeProperties.version 字段以获取 QR 码的版本。 如果类型为 QRCodeType.QRCode,则该值范围为 1 到 40,如果类型为 QRCodeType.MicroQRCode,则范围为 1 到 4。

或者,传递 ARMarker 对象的可跟踪 ID 以获取 ARMarkerManager.GetQRCodeProperties(TrackableId) QR 码的类型和版本。

警告

QR 码是当前唯一支持的标记类型,尽管将来的版本中可能会添加对其他标记类型的支持。 如果 markerType 不是 ARMarkerType.QRCode,则调用 GetQRCodeProperties(TrackableId)System.InvalidOperationException引发。 如果这可能会导致应用以后出现问题,请考虑在 try-catch 块中包装调用 GetQRCodeProperties(TrackableId)

读取 QR 数据

ARMarker组件附加到创建的每个GameObjectARMarkerManager组件。 ARMarker 提供两种返回 QR 码数据的方法:

以下代码演示了基本用法 GetDecodedString()GetRawData(Unity.Collections.Allocator allocator)

using System;
using Microsoft.MixedReality.OpenXR;

// ...

void OnQRCodesChanged(ARMarkersChangedEventArgs args)
{
    foreach (ARMarker qrCode in args.added)
    {
        var text = qrCode.GetDecodedString();
        Debug.Log($"QR code text: {text}");

        var bytes = qrCode.GetRawData(Unity.Collections.Allocator.Temp);
        Debug.Log($"QR code bytes: {bytes.Length}");
        bytes.Dispose();
    }
}

获取 QR 码大小、位置、旋转和居中

对象 ARMarker 提供它所表示的 QR 码的大小、位置、旋转和中心。

若要获取 QR 码的大小(以米为单位),请使用属性 ARMarker.size

使用该 ARMarker.transform 属性获取 QR 码转换的旋转和世界空间位置,以及 ARMarker.center QR 码相对于 QR 码转换的 2D 坐标。 转换本身根据ARMarker.transformMode(转换模式)设置为TransformMode.MostStable最稳定、QR 码的左上角)或TransformMode.Center居中,QR 码的几何中心)居中。

使用 ARMarkerManager.defaultTransformMode 字段设置转换模式 ARMarkerManager 可创建包含的新 ARMarker 对象。 该字段使用 Default Transform Mode 该字段设置为在 Unity 检查器中初始化,如下所示:

ARMarkerManager 组件的默认转换模式检查器字段

作为使用替代方法 ARMarker.transformMode,传递 ARMarker 对象的可跟踪 ID 以 ARMarkerManager.SetTransformMode(TrackableId, TransformMode) 设置其转换模式。

以下代码演示如何获取新的 QR 码的大小和中心、转换的位置和旋转,以及更改转换模式后更新的转换位置。

using System;
using Microsoft.MixedReality.OpenXR;

// ...

void OnMarkersChanged(ARMarkersChangedEventArgs args)
{
    Debug.Log($"Default transform mode is {ARMarkerManager.Instance.defaultTransformMode}./n");

    if (e.added.Count > 0)
    {
        ARMarker qrCode = args.added[0];

        Debug.Log($"Position: {qrCode.transform.position}");
        Debug.Log($"Rotation: {qrCode.transform.rotation}");
        Debug.Log($"Center: {qrCode.center}");

        if (qrCode.transformMode == TransformMode.Center)
            qrCode.transformMode = TransformMode.MostStable;
        else
            qrCode.transformMode = TransformMode.Center;

        Debug.Log($"QR code's transform mode is now set to {qrCode.transformMode}. /n");
        Debug.Log($"New position: {qrCode.transform.position}");
    }
}

AR 标记示例方案

随 OpenXR 插件包一起提供的示例包含启用了 QR 码的场景,该场景提供了如何使用 ARMarkerManagerARMarker 用法的示例。

场景位于 Assets > ARMarker 中,如下所示:ARMarker 场景资产位置

可以在 GitHub 上的 OpenXR Unity 混合现实示例存储库中找到场景中使用的 C# 脚本:/OpenXR-Unity-MixedReality-Samples/tree/main/SampleScenarios/Scenarios/MarkerSample/Scripts

另请参阅