1. 總覽
ARCore 是 Google 在智慧型手機上打造擴增實境體驗的架構。您可以使用 Unity 的 AR Foundation 建構跨平台 AR 應用程式。
建構項目
在本程式碼研究室中,您將使用 AR Foundation 建構簡單的遊戲。遊戲的目標是透過您手持裝置控制的車輛來收集包裹。
然而,這個想法並不在完全虛擬世界裡發生!您將混合使用實體原子和數位位元,打造出可理解玩家周遭環境的遊戲,帶來全新類型的玩家體驗。
完成本程式碼研究室後,您的遊戲將具備以下能力:
- 可偵測真實世界的飛機,並在上面繪製遊戲場。
- 從攝影機視角投放光線,偵測與飛機的十字路口。
- 根據現實世界的光線條件做出反應,為遊戲增添真實感。
課程內容
- 如何設定使用 Unity 的 AR Foundation 的專案。
- 如何使用
ARPlaneManager
訂閱新飛機。 - 如何使用
Raycast
尋找具有虛擬幾何圖形的十字路口 - 如何使用
ARLightEstimationData
為場景打光。
軟硬體需求
- 使用支援的 ARCore 裝置,使用 USB 傳輸線連接至開發機器。
- Google Play 服務 - AR 適用 1.23 以上版本。
- Unity Hub 或 Unity 2020 LTS 安裝。
2. 設定開發環境
在這個步驟中,您可以使用 Unity 的 AR 基礎打造開發環境。
確認您的裝置與 AR 相容
Android 裝置上的 AR 體驗是由 ARCore 所驅動,適用於支援 ARCore 的裝置。確認開發裝置與 AR 相容。或者,您也可以使用正確設定的與 AR 相容的 Android Emulator 執行個體。
在裝置上設定 USB 偵錯功能
您必須在裝置上啟用「開發人員選項」才能執行偵錯應用程式。如果您尚未這麼做,請參閱 Android 說明文件中的啟用開發人員選項和 USB 偵錯。
安裝 Unity (2020.3 LTS)
在工作站上安裝 Unity 2020 LTS。在本程式碼研究室中,適用於 2020.3 (LTS) 版中的 Unity 使用者介面螢幕截圖。其他版本的 Unity 或許也能正常運作,但可能需要執行其他步驟。實際畫面可能與這裡顯示的螢幕截圖不同。
建立新專案
使用「Universal Render Pipeline」範本建立新專案。輸入描述性的名稱和適當的位置,然後按下「建立」。
安裝所需架構
您可以在 Unity Package Manager 中找到 Unity 的 AR Foundation。
- 按一下「視窗」圖示 > 套件管理員。
- 在這個視窗中,安裝您將在本程式碼研究室中使用的套件。使用
►
圖示展開項目,即可查看這些架構的最新版本。為下列各個架構安裝最新版本:- AR 基礎
- ARCore XR 外掛程式
完成後,檔案包管理員看起來會像這樣:
安裝入門套件
在本程式碼研究室中,我們提供了包含 PrefAb 的入門套件和指令碼,可加快程式碼研究室的某些部分,讓您專注於如何使用 AR Foundation。
變更版本設定
由於應用程式將在 Android 上執行,因此請將建構平台變更為 Android:
- 開啟「檔案」版本設定。
- 在「Platform」窗格中,選取「Android」。
- 或者,您也可以啟用「Development Build」和「Script Debugging」,以便在應用程式執行時保留偵錯資訊。
- 按一下「切換平台」。
變更專案設定
您必須設定 AR Foundation,才能在啟動時初始化 XR 系統。
- 開啟「編輯」>「編輯」專案設定...,然後按一下 XR 外掛程式管理部分。
- 在「Android」分頁中,啟用「ARCore」。
- 按一下左側窗格中的「Player」區段。
- 在「Android」分頁的「Other Settings」下方,將「Vulkan」從「Graphics API」中移除。
- 使用 ARCore 的 AR 必要應用程式需要最低 API 級別 24。向下捲動並找到「Minimum API Level」。將最低 API 級別設為 24。
新增必要的場景元素
「Universal Render Pipeline」範本內含一些您在本教學課程中無法使用的遊戲物件。
- 刪除
SampleScene
中的所有遊戲物件。
- 新增 AR Foundation 物件。在「Hierarchy」(階層) 窗格中按一下滑鼠右鍵。你可以使用這個選單新增:
- XR >AR 工作階段:這個物件可控制 AR 體驗的生命週期。
- XR >AR 工作階段來源:這個物件會將 AR 座標轉換為 Unity 世界座標。
- 淺色 >定向光源:這個光源可顯示遊戲物體。
您的階層結構應如下所示:
- 展開您在階層中建立的「AR Session Origin」,然後選取「AR Camera」物件。在檢查器中,將其標記變更為「MainCamera」。MainCamera
設定轉譯功能
Unity 的 Universal Render Pipeline 需要做出一項變更,才能與 AR Foundation 相容。
- 在「專案」專案窗格中,瀏覽資產>設定以尋找 ForwardRenderer 資產。
- 選取「ForwardRenderer」ForwardRenderer。
- 在「Inspector」窗格中,使用「Add Renderer Feature」新增 AR 背景轉譯器功能。這個元件會在場景中算繪攝影機畫面。
驗證設定
- 確認裝置已接上電源,且 ADB 偵錯功能已開啟。
- 按一下「檔案」>建構及執行...應用程式會將應用程式上傳至你的裝置,並在安裝完成後啟動。
- 您應該會在裝置的螢幕上看到攝影機畫面。
在下一個步驟中,您將開始為應用程式新增功能。
3. 偵測真實世界中的飛機
設定基本場景後,即可開始開發遊戲。在這個步驟中,您可以偵測飛機,並繪製到場景中。
新增 ARPlaneManager
元件
ARPlaneManager
會偵測 ARPlane
,並在裝置掌握環境變化時建立、更新及移除遊戲物件。
- 使用階層窗格建立空白的
GameObject
。 - 將其重新命名為
Driving Surface Manager
。這個元件會顯示飛機,直到玩家選擇飛機為止。 - 選取新遊戲物件。在「Inspector」窗格中,按一下「Add Component」新增「AR Plane Manager」。
- 設定
Plane Prefab
欄位以設定ARPlaneManager
:- 按一下
None
旁的按鈕,開啟「Select GameObject」視窗。 - 選取「Assets」(資產) 分頁標籤,然後搜尋「Driving Surface Plane」。
- 按一下
此入門套件中的這項預先設定提供了粗糙的落地紋理,用來作為飛機裝飾。
- 將
Detection Mode
變更為Horizontal
。這會將ARPlaneManager
設定為僅提供水平平面,非常適合在行駛期間。
新增 ARRaycastManager
元件
ARRaycastManager
會公開 raycast 功能。在下一個步驟中,我們會使用此物件為使用者提供控制項。
- 確認已在階層窗格中選取名為
Driving Surface Manager
的物件。 - 在檢查器中按一下「Add Component」,即可在遊戲物件中加入
ARRaycastManager
元件。
這個元件不需要進一步設定。
新增 DrivingSurfaceManager
元件
DrivingSurfaceManager
是 Starter 套件的輔助指令碼,可用來選取 ARPlane
。選取 ARPlane
後,系統會隱藏所有其他飛機,並停用新飛機。
- 確認已在階層窗格中選取名為
Driving Surface Manager
的物件。 - 在檢查器中按一下「Add Component」,即可在遊戲物件中加入
DrivingSurfaceManager
元件。
這個元件不需要進一步設定。
執行應用程式
- 按一下「檔案」>建構並執行...測試變更。
- 將裝置指向現實生活中的水平表面,並四處移動裝置,讓 ARCore 更瞭解全世界。
- ARCore 偵測到平面後,您應該會在真實世界表面看到髒汙紋理。
ARPlaneManager
會為每個偵測到的平面將指定的Plane Prefab
例項化。Driving Surface Plane
Prefab 具有ARPlaneMeshVisualizer
元件,可針對指定的ARPlane
建立網格。
在下一個步驟中,您將使用偵測到的飛機做為遊戲場。
4. 針對偵測到的平面執行命中測試
在上一個步驟中,您編寫了可偵測飛機的應用程式。這些飛機會顯示在遊戲場景中。現在,只要建立目標腳架和車輛,就能行駛在偵測到的飛機表面上,為這些飛機增添互動。
構思瞄準目標
這個應用程式的控製配置涉及玩家將手機指向表面。為了清楚呈現指定地點的視覺回應,您需使用瞄準鏡腳。
為了「固定」最好是 命中測試命中測試是一種在特定方向轉換射線時計算交叉點的技術。您將使用命中測試來偵測相機視角方向的十字路口。
加入裝飾物
- 在靠近畫面底部的專案窗格中,前往「資產」資產>入門套件。
- 將 Reticle Prefab 拖曳至專案的階層窗格,然後將其拖曳至場景中。
- 選取階層中的裝飾物。
- 在檢查器中,按一下「Add Component」。從入門套件新增
ReticleBehaviour
指令碼。這段指令碼包含控制分段的樣板, ReticleBehaviour
指令碼依附於您先前建立的Driving Surface Manager
,因此請按一下Driving Surface Manager
選擇工具新增依附元件。選取「Scene」分頁標籤,然後選擇Driving Surface Manager
。
編輯ReticleBehaviour
ReticleBehavior
指令碼會將掛鉤放在裝置可視區域中央的平面上。
- 按兩下
Script
欄位,開啟ReticleBehaviour.cs
指令碼。 - 使用相機的
ViewToScreenPoint
來判斷畫面中心。請編輯Update()
方法,新增以下內容:
var screenCenter = Camera.main.ViewportToScreenPoint(new Vector3(0.5f, 0.5f));
- 請運用這個焦點進行光線轉換。新增下列程式碼:
var hits = new List<ARRaycastHit>();
DrivingSurfaceManager.RaycastManager.Raycast(screenCenter, hits, TrackableType.PlaneWithinBounds);
變數 hits
會包含 ARRaycastHit
,用來說明 ray
與可追蹤項目上的點。
- 查詢
hits
清單,判斷交叉點。優先處理DrivingSurfaceManager
中的已上鎖層,如果不存在,請使用第一次的飛機命中。請將下列程式碼新增至Update()
的結尾:
CurrentPlane = null;
ARRaycastHit? hit = null;
if (hits.Length > 0)
{
// If you don't have a locked plane already...
var lockedPlane = DrivingSurfaceManager.LockedPlane;
hit = lockedPlane == null
// ... use the first hit in `hits`.
? hits[0]
// Otherwise use the locked plane, if it's there.
: hits.SingleOrDefault(x => x.trackableId == lockedPlane.trackableId);
}
- 如果
hit
含有結果,請將這個GameObject
的轉換移至命中位置。
if (hit.HasValue)
{
CurrentPlane = DrivingSurfaceManager.PlaneManager.GetPlane(hit.Value.trackableId);
// Move this reticle to the location of the hit.
transform.position = hit.Value.pose.position;
}
Child.SetActive(CurrentPlane != null);
測試模型
- 按一下「檔案」>建構並執行...測試變更。
- 只要將裝置對準飛機,你應該會看到螺絲跟隨攝影機的動作。
建立汽車
玩家將控制一輛玩具車,並驅動車子前往庫存地點。入門套件提供這輛車的型號和行為。
將 CarManager
新增至場景
- 在「階層」中,建立新的空白
GameObject
。 - 將其重新命名為
Car Spawner
。 - 選取您建立的物件。在「Hierarchy」(階層) 窗格中,按一下「Add Component」新增
CarManager
元件。 - 按一下每個欄位的選擇工具,即可設定
CarManager
的依附元件:- Car Prefab:在「Assets」中選取「Car Prefab」。
- Reticle:在「Scene」中選取「Reticle Prefab」。
- 駕駛 Surface Manager:在「Scene」中,選取「Driving Surface Manager」。
這個 CarManager
行為會在掛鉤開啟的飛機上產生玩具車。如有需要,可以參閱 CarBehaviour
指令碼,瞭解車輛的程式設計方式。
試駕
- 按一下「檔案」>建構並執行測試變更。
- 當你輕觸飛機時,該地點應該會顯示小型車輛。這輛車會遵循牆面。
新增遊戲元素
現在,玩家可以控制場景中的實體,請為玩家提供前進方向的目的地。
- 在階層中建立新的空白
GameObject
。 - 將其重新命名為
Package Spawner
。 - 選取您建立的物件。在「Hierarchy」(階層) 窗格中,按一下「Add Component」新增
PackageSpawner
元件。 - 按一下每個欄位的選擇工具,即可設定
PackageSpawner
的依附元件:- Package Prefab:在「Assets」中選取「Package Prefab」。
- 在「Scene」(情境) 中,選取「Driving Surface Manager」。
如果沒有套件,此 PackageSpawner
行為會在鎖定的 ARPlane
上的隨機位置產生新套件。
測試遊戲
- 按一下「檔案」>建構並執行測試變更。2. 建立汽車後,系統應該會產生一個包裹。
- 開車上車。
- 新名稱會隨機顯示。
5. 設定光線預估
基本遊戲到此結束後,請在 AR 場景中加入寫實程度。在這個步驟中,您將使用 ARCore 的 Lighting Estimation API,根據收到的相機畫面偵測真實世界中的光線。這項資訊將用於調整場景的亮度,以配合現實世界的光線。
啟用燈光估計
- 在「階層」中,展開「AR 工作階段來源」,然後選取「AR 相機」物件。
- 在「Inspector」中,展開「AR Camera Manager」指令碼。
- 將「亮度估算」欄位變更為「全部」。
調整方向光源
- 在「階層」中,選取「定向光源」物件。
- 在其中新增
LightEstimation
元件。入門套件的這個元件提供了用於訂閱燈光變更的樣板。 - 在
FrameReceived()
函式中新增:
ARLightEstimationData lightEstimation = args.lightEstimation;
if (lightEstimation.averageBrightness.HasValue)
Light.intensity = lightEstimation.averageBrightness.Value;
if (lightEstimation.averageColorTemperature.HasValue)
Light.colorTemperature = lightEstimation.averageColorTemperature.Value;
if (lightEstimation.colorCorrection.HasValue)
Light.color = lightEstimation.colorCorrection.Value;
if (lightEstimation.mainLightDirection.HasValue)
Light.transform.rotation = Quaternion.LookRotation(lightEstimation.mainLightDirection.Value);
if (lightEstimation.mainLightColor.HasValue)
Light.color = lightEstimation.mainLightColor.Value;
if (lightEstimation.mainLightIntensityLumens.HasValue)
Light.intensity = lightEstimation.averageMainLightBrightness.Value;
if (lightEstimation.ambientSphericalHarmonics.HasValue)
{
RenderSettings.ambientMode = AmbientMode.Skybox;
RenderSettings.ambientProbe = lightEstimation.ambientSphericalHarmonics.Value;
}
測試變更
- 按一下「檔案」>建構並執行測試變更。
- 查看場景中的物體時,你可能會發現這些物體顏色會因環境光線而異。
- 如果可以,請嘗試調整亮度。舉例來說,你可以將所在房間的燈關掉。您應該會看到物體上的光線根據實際光線的變化自動調整。
6. 總結
恭喜!您已經到 Unity AR Foundation 本程式碼研究室的結尾,
涵蓋內容
- 如何使用 Unity 的 AR 基礎和 Universal Rendering Pipeline 設定基本專案。
- 如何使用
ARPlaneManager
訂閱新飛機。 - 如何使用
Raycast
尋找具有虛擬幾何圖形的十字路口。 - 如何使用
ARLightEstimationData
為場景打光。
後續步驟
- 請參閱 Unity 的 AR 基礎範例。
- 瀏覽 AR 基礎說明文件。
- 請參閱 Google 說明文件,瞭解 Unity 的 AR 基金會適用的 ARCore 擴充功能。
獎勵作業
如果您想拓展自己在這裡打造的遊戲,可以思考以下幾個構想:
- 在
PackageManager
產生新套件時修改TextMeshPro
,為遊戲新增分數計數器。 - 啟用「Performance Overlay」,即可在遊戲執行期間查看效能資訊。
- 使用永久性 Raycasts 先在場景中放置新物件。偵測到該區域的飛機時,該物體會更新以貼齊該平面。