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 Foundation 進行開發。
確認您的裝置與 AR 相容
Android 裝置上的 AR 體驗是由 ARCore 所驅動,適用於支援 ARCore 的裝置。確認開發裝置與 AR 相容。或者,您也可以使用正確設定的與 AR 相容的 Android Emulator 執行個體。
在裝置上設定 USB 偵錯功能
您必須在裝置上啟用「開發人員選項」才能執行偵錯應用程式。如果您尚未這麼做,請參閱 Android 說明文件中的啟用開發人員選項和 USB 偵錯。
安裝 Unity (2020.3 LTS)
在工作站上安裝 Unity 2020 LTS。在本程式碼研究室中,我們會顯示 2020.3 (LTS) 版本中 Unity 的 UI 螢幕截圖。其他版本的 Unity 可能也能運作,但可能需要額外步驟。實際畫面可能與這裡顯示的螢幕截圖不同。
建立新專案
使用「Universal Render Pipeline」範本建立新專案。為檔案命名並指定適當的位置,然後按一下「建立」。
安裝所需架構
您可以在 Unity Package Manager 中找到 Unity 的 AR Foundation。
- 按一下「視窗」圖示 > 套件管理員。
- 在這個視窗中,安裝您將在本程式碼研究室中使用的套件。使用
►
圖示展開項目,即可查看這些架構的最新版本。為下列各個架構安裝最新版本:- AR Foundation
- ARCore XR 外掛程式
完成後,檔案包管理員看起來會像這樣:
安裝啟動包
在本程式碼研究室中,我們提供了包含 PrefAb 的入門套件和指令碼,可加快程式碼研究室的某些部分,讓您專注於如何使用 AR Foundation。
變更版本設定
由於應用程式將在 Android 上執行,因此請將建構平台變更為 Android:
- 開啟「檔案」版本設定。
- 在「Platform」窗格中,選取「Android」。
- 或者,您也可以啟用「Development Build」和「Script Debugging」,以便在應用程式執行時保留偵錯資訊。
- 按一下「Switch Platform」。
變更專案設定
您必須設定 AR Foundation,才能在啟動時初始化 XR 系統。
- 開啟「編輯」>「編輯」專案設定...,然後按一下 XR 外掛程式管理部分。
- 在「Android」分頁中,啟用「ARCore」。
- 按一下左側窗格中的「Player」區段。
- 在「Android」分頁的「Other Settings」下方,將「Vulkan」從「Graphics API」中移除。
- 使用 ARCore 的 AR 必要應用程式,其 API 級別必須至少為 24。向下捲動,然後找出「Minimum API Level」。將最低 API 級別設為 24。
新增必要的場景元素
通用算繪管道範本會附帶一些您不會在本教學課程中使用的遊戲物件。
- 刪除
SampleScene
中的所有遊戲物件。
- 新增 AR Foundation 物件。在「層級結構」窗格中按一下滑鼠右鍵。你可以使用這個選單新增:
- XR > AR 工作階段:這個物件會控管 AR 體驗的生命週期。
- XR >AR 工作階段來源:這個物件會將 AR 座標轉換為 Unity 世界座標。
- Light > Directional Light:提供光源,可照亮遊戲物件。
你的階層應如下所示:
- 展開在階層中建立的 AR 工作階段來源,然後選取 AR 相機物件。在檢查器中,將標記變更為 MainCamera。
設定轉譯功能
Unity 的 Universal Render Pipeline 需要做出一項變更,才能與 AR Foundation 相容。
- 在「專案」專案窗格中,瀏覽資產>設定以尋找 ForwardRenderer 資產。
- 選取「ForwardRenderer」ForwardRenderer。
- 在「檢查器」窗格中,使用「Add Renderer Feature」新增「AR Background Renderer Feature」。這個元件會在場景中算繪攝影機畫面。
確認設定
- 確認裝置已接上電源,且 ADB 偵錯功能已開啟。
- 依序按一下「File」>「Build And Run...」應用程式會將應用程式上傳至你的裝置,並在安裝完成後啟動。
- 裝置螢幕上應會顯示攝影機畫面。
在下一個步驟中,您將開始為應用程式新增功能。
3. 偵測真實世界中的飛機
設定基本場景後,即可開始開發遊戲。在這個步驟中,您可以偵測飛機,並繪製到場景中。
新增 ARPlaneManager
元件
ARPlaneManager
會偵測 ARPlane
,並在裝置對環境的瞭解有所變更時建立、更新及移除遊戲物件。
- 使用階層窗格建立空白的
GameObject
。 - 將其重新命名為
Driving Surface Manager
。這個元件會顯示飛機,直到玩家選擇飛機為止。 - 選取新遊戲物件。在「檢查器」窗格中,按一下「新增元件」,即可新增「AR 平面管理工具」。
- 設定
Plane Prefab
欄位以設定ARPlaneManager
:- 按一下
None
旁的按鈕,開啟「Select GameObject」視窗。 - 選取「Assets」(資產) 分頁標籤,然後搜尋「Driving Surface Plane」。
- 按一下
此入門套件中的這項預先設定提供了粗糙的落地紋理,用來作為飛機裝飾。
- 將
Detection Mode
變更為Horizontal
。這會將ARPlaneManager
設為只提供水平平面,非常適合在行駛時使用。
新增 ARRaycastManager
元件
ARRaycastManager
會公開光線投射功能。在下一個步驟中,我們會使用此物件為使用者提供控制項。
- 確認「階層」窗格中已選取名為
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
預製模組含有ARPlaneMeshVisualizer
元件,可為特定ARPlane
建立網格。
在下一個步驟中,您將使用偵測到的平面做為遊戲場地。
4. 針對偵測到的平面執行命中測試
在上一個步驟中,您編寫了可偵測飛機的應用程式。這些平面會反映在遊戲的場景中。接下來,您將建立瞄準十字準線和車輛,讓車輛在偵測到的平面上行駛,藉此增加與這些平面的互動性。
建立瞄準十字準線
這個應用程式的控制配置涉及玩家將手機對準表面。為了清楚呈現指定地點的視覺回應,您需使用瞄準鏡腳。
如要將這個十字準線「黏附」到 AR 平面,請使用命中測試。命中測試是一種在特定方向轉換射線時計算交叉點的技術。您將使用命中測試來偵測相機視角方向的十字路口。
加入裝飾物
- 在畫面底部附近的「Project」窗格中,依序前往「Assets」>「Starter Package」。
- 將十字準星預設物件拖曳至專案的階層窗格,放入場景中。
- 在階層結構中選取十字準星。
- 在檢查器中,按一下「Add Component」。從入門套件新增
ReticleBehaviour
指令碼。這個指令碼包含用於控制十字準線的部分樣板。 ReticleBehaviour
指令碼會依賴您先前建立的Driving Surface Manager
,因此請按一下Driving Surface Manager
選擇器,新增依附元件。選取「場景」分頁標籤,然後選擇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);
測試模型
- 按一下「檔案」>建構並執行...測試變更。
- 只要將裝置對準飛機,你應該會看到螺絲跟隨攝影機的動作。
建立車輛
玩家將控制玩具車,朝準星的位置行駛。這個車輛的模型和行為會在 Starter Package 中提供。
將 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
指令碼,瞭解車輛的程式設計方式。
試駕
- 按一下「File」>「Build And Run」即可測試變更。
- 輕觸飛機後,畫面上會顯示一輛小車。這輛車會遵循牆面。
新增遊戲元素
玩家現在可以控制場景中的實體,請為玩家提供要前往的目的地。
- 在階層中建立新的空白
GameObject
。 - 將其重新命名為
Package Spawner
。 - 選取您建立的物件。在「Hierarchy」(階層) 窗格中,按一下「Add Component」新增
PackageSpawner
元件。 - 按一下每個欄位的選擇工具,即可設定
PackageSpawner
的依附元件:- Package Prefab:在「Assets」中選取「Package Prefab」。
- 駕駛介面管理工具:在「場景」中,選取「駕駛介面管理工具」。
如果沒有套件,此 PackageSpawner
行為會在鎖定的 ARPlane
上的隨機位置產生新套件。
測試遊戲
- 按一下「File」>「Build And Run」即可測試變更內容。2. 建立車輛後,應會產生套件。
- 開車上車。
- 新名稱會隨機顯示。
5. 設定光線預估
基本遊戲完成後,您可以為 AR 場景增添一點寫實感。在這個步驟中,您將使用 ARCore 的 Lighting Estimation API,根據收到的相機畫面偵測真實世界中的光線。系統會根據這項資訊調整場景的照明,以符合實際光線。
啟用燈光估計
- 在「Hierarchy」中展開「AR Session Origin」,然後選取「AR Camera」物件。
- 在「Inspector」中,展開「AR Camera Manager」指令碼。
- 將「亮度估算」欄位變更為「全部」。
調整方向光源
- 在「階層」中,選取「定向光源」物件。
- 在其中新增
LightEstimation
元件。Starter Package 中的這個元件提供一些模板,可用於訂閱照明變更。 - 在
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 Foundation 範例。
- 瀏覽 AR Foundation 說明文件。
- 請參閱 Google 說明文件,瞭解 Unity 的 AR 基金會適用的 ARCore 擴充功能。
獎勵作業
如果您想擴充在此建立的遊戲,可以參考以下想法:
- 在
PackageManager
產生新套件時修改TextMeshPro
,為遊戲新增分數計數器。 - 啟用「Performance Overlay」,即可在遊戲執行期間查看效能資訊。
- 請先使用持久性光線投射功能,將新物件放入場景。當系統在該區域偵測到平面時,該物件就會更新,以便對齊該平面。