Unity 中的 QR 代碼
HoloLens 2 頭戴式裝置可以追蹤及偵測可用來提供全像投影和其他 AR 功能的 QR 代碼。 本文會引導您完成在 Unity 應用程式中開始使用 QR 代碼所需的一切,包括:
- 將 QR 代碼偵測新增至 Unity 應用程式。
- 瞭解您需要使用的重要概念和 Unity 元件。
- 提供涵蓋常見 QR 代碼使用方式的教學課程。
- 介紹 AR 標記範例案例,示範已啟用 QR 代碼的場景和範例腳本。
在繼續本文之前,建議您先流覽 QR 代碼概觀。
設定 Unity 專案和應用程式
您的 Unity 專案和應用程式必須正確設定並設定,才能啟用 QR 代碼功能,這需要:
- 適用於 Windows Mixed Reality 113.2403.5001 或更新版本的 OpenXR。
注意
這隨附於操作系統,並可透過 Windows 市集進行更新。 請注意,使用者可能已安裝舊版,且其裝置將無法使用AR標記,例如QR代碼,直到更新至113.2403.5001版或更新版本為止。
- 與支援的 Unity 版本相容的專案:
- Unity 2022.3 LTS (建議)
- Unity 2021.3 LTS
- 混合實境 OpenXR 外掛程式。
- 為您的 Unity 專案啟用網路攝影機功能。
- 授與應用程式的相機許可權。
下列各節將引導您瞭解如何設定 Unity 專案和應用程式,以啟用 QR 代碼偵測。
取得混合實境 OpenXR 外掛程式
混合實境 OpenXR 外掛程式套件包含可用來存取 QR 代碼功能的 C# API。
若要匯入套件:
混合實境功能工具也可簡化套件管理,並可用來尋找、更新及新增應用程式所需的混合實境功能。 如需如何使用此工具的詳細指示,請參閱 歡迎使用混合實境功能工具 。
啟用 WebCam 功能
若要偵測和追蹤 QR 代碼,您的 Unity 專案必須 啟用 WebCam 功能。
若要啟用 WebCam 功能:
- 開啟 Unity 專案。
- 按兩下 Unity 編輯器應用程式選單中的 [編輯 ]。
- 移至 [項目設定 > 播放機 ],然後選取 [UWP ] 索引標籤,如下所示:
- 在 [功能] 列表中啟用 WebCam。
- 結束 項目設定。
您的 Unity 應用程式現在已啟用 WebCam 功能。 不過,您的應用程式仍必須獲得存取裝置相機的許可權。
授與您的應用程式相機訪問許可權
如果您的應用程式 已啟用 WebCam 功能,[許可權] 對話方塊會提示使用者將裝置相機的存取權授與您的應用程式。
此對話框只會向用戶顯示一次,通常是在輸入包含ARMarkerManager
已啟用 QR 代碼標記支援的場景時。 如果拒絕相機存取,使用者可以移至 [ 設定 > 應用程式 ],並透過應用程式的 [進階選項] 加以啟用。
將 QR 代碼偵測建置至場景
QR 代碼偵測必須內建於您想要在其中使用 QR 代碼的每個場景,這需要:
GameObject
附加的ARMarkerManager
。ARMarkerManager
只負責建立、更新和移除每個GameObject
偵測到的 QR 代碼。- 附加的
ARMarker
預製專案。 ARMarkerManager
設定為在偵測到 QR 代碼時建立GameObject
時使用預製專案。
建立 QR 代碼的預製專案
若要在場景中使用 QR 代碼,您必須建立 QR 代碼的預製專案。 ARMarkerManager
使用此預製專案,在偵測到 QR 代碼時從 建立 GameObject
。
若要製作 QR 代碼的預製專案:
- 為您的專案建立新的預製專案 。
- 將
ARMarker
元件新增至 prefab,位於 Script > Microsoft.MixedReality.OpenXR > ARMarker 底下。
您現在有要使用的基本預製專案。 您可能想要讓應用程式以可視化方式呈現環境中偵測到的 QR 代碼。 下一節將逐步引導您新增 QR 代碼的視覺表示法。
新增視覺效果
在上一節中,新增 ARMarker
至預製專案也會自動新增 ARMarkerScale
元件。 此元件用來比對 QR 代碼視覺表示法與其實體對應項目的規模。
若要這麼做︰
- 將空白
GameObject
新增至您在上一節中建立的預製專案。 它會代表所有視覺 標記內容。 - 將子 3D
GameObject
,例如Quad
,新增至標記內容GameObject
。 - 在預製項目元件中
ARMarkerScale
,將 [標記尺規轉換] 設定為標記內容GameObject
。 設定此欄位可確保您選擇的 3DGameObject
已正確調整,以符合真實世界的 QR 代碼。
新增 ARMarkerManager
至場景
ARMarkerManager
只負責建立、更新和移除每個 GameObject
偵測到的 QR 代碼。
若要新增 ARMarkerManager
至您的場景:
- 將 放入
GameObject
您的場景。 - 將
ARMarkerManager
元件新增至GameObject
位於 Script > Microsoft.MixedReality.OpenXR > ARMarkerManager 底下的 。
- 將 [
ARMarkerManager
標記預製專案] 字段設定為您在上一節中建立的預製專案。 - 展開 [啟用標記類型],然後選擇元素,並將其設定為 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 代碼的可追蹤識別碼
QR 代碼是 可追蹤的,這是AR裝置可在實體環境中偵測和追蹤的任何專案。 可追蹤專案衍生自提供標識碼、追蹤狀態、姿勢和其他數據的型 ARTrackable<TSessionRelativeData, TTrackable>
別。
QR 代碼的可追蹤識別碼可以傳遞至 ARMarkerManager
方法來取得 QR 代碼的屬性、原始位元組資料和字串表示,以及設定 QR 代碼的轉換模式。 這些方法可讓您擷取 QR 代碼的數據,而不需要保留 ARMarker
對象參考。
您可以將 QR 代碼的識別碼傳遞至下列 ARMarkerManager
方法:
GetDecodedString(UnityEngine.XR.ARSubsystems.TrackableId trackableId)
GetMarker(UnityEngine.XR.ARSubsystems.TrackableId trackableId)
GetQRCodeProperties(UnityEngine.XR.ARSubsystems.TrackableId)
GetRawData(UnityEngine.XR.ARSubsystems.TrackableId, Unity.Collections.Allocator)
SetTransformMode(UnityEngine.XR.ARSubsystems.TrackableId, Microsoft.MixedReality.OpenXR.TransformMode)
注意
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 代碼的物件,並將其可追蹤標識碼寫入 [偵錯] 視窗。
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 代碼的版本和類型:
- 呼叫
ARMarker.GetQRCodeProperties()
會傳回 實例的QRCodeProperties
。 - 存取傳回值中的欄位
QRCodeProperties
,以取得 QR 代碼的類型。 值為QRCodeType.QRCode
或QRCodeType.MicroQRCode
。 - 存取傳回值欄位
QRCodeProperties.version
以取得 QR 代碼的版本。 如果類型為 ,則此值的範圍從 1 到 40,如果類型為QRCodeType.QRCode
QRCodeType.MicroQRCode
,則從 1 到 4。
或者,傳遞 ARMarker
物件的可追蹤標識碼, ARMarkerManager.GetQRCodeProperties(TrackableId)
以取得 QR 代碼的類型和版本。
警告
QR 代碼是目前唯一支援的標記類型,不過未來版本中可能會新增其他標記類型的支援。 如果 markerType
不是 ARMarkerType.QRCode
,則呼叫 GetQRCodeProperties(TrackableId)
會 System.InvalidOperationException
擲回 。 如果這可能會在稍後於您的應用程式中造成問題,請考慮將呼叫 GetQRCodeProperties(TrackableId)
包裝在 try-catch 區塊中。
讀取 QR 數據
元件ARMarker
會附加至每個GameObject
ARMarkerManager
建立的元件。 ARMarker
提供兩個傳回 QR 代碼資料的方法:
GetDecodedString()
:這個方法會取得 QR 代碼的字串表示法,例如 URL。GetRawData(Unity.Collections.Allocator allocator)
:這個方法會以位元組陣列的形式傳回 QR 代碼內容,以微調數位列的配置方式。 在經常性路徑和其他效能十分重要的情況下,使用此方法。
下列程式代碼示範 和GetRawData(Unity.Collections.Allocator allocator)
的基本用法GetDecodedString()
:
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 代碼的 2D 座標,相對於 QR 代碼的轉換。 轉換本身會根據 ARMarker.transformMode
[轉換模式] 設定TransformMode.MostStable
為 (最穩定、QR 代碼的左上方) 或 TransformMode.Center
(置中,QR 代碼的幾何中心) 來置中。
ARMarkerManager.defaultTransformMode
使用欄位來設定轉換模式ARMarkerManager
會使用 建立新的 ARMarker
物件。 欄位會 Default Transform Mode
使用 字段初始化,在 Unity Inspector 中設定為 ,如下所示:
若要替代使用 ARMarker.transformMode
,請將物件的可追蹤標識元傳遞 ARMarker
至 以 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 代碼的場景,提供如何使用 ARMarkerManager
和 ARMarker
的範例。
場景位於 Assets > ARMarker 中 ,如下所示:
您可以在 GitHub 上的 OpenXR Unity 混合實境範例存放庫中找到場景中使用的 C# 腳本:/OpenXR-Unity-MixedReality-Samples/tree/main/SampleScenarios/Scenarios/MarkerSample/Scripts