??VR 一體機(jī)內(nèi)置操作系統(tǒng),是具備獨(dú)立處理器的 VR 頭戴式顯示設(shè)備。VR 一體機(jī)具備獨(dú)立運(yùn)算、輸入和輸出的功能不如主機(jī)式 VR 設(shè)備強(qiáng)大,但由于沒(méi)有連線的束縛,使用起來(lái)自由度更高。
??VR 一體機(jī)作為市面上應(yīng)用最為廣泛的虛擬現(xiàn)實(shí)設(shè)備,是虛擬現(xiàn)實(shí)應(yīng)用開發(fā)的主要設(shè)備。典型的 VR 一體機(jī)設(shè)備為 Oculus Quest 2、Pico Neo 2,這里以 Pico Neo 為例介紹 VR 一體機(jī)設(shè)備的應(yīng)用開發(fā)。
1.設(shè)備介紹
??Pico Neo 是市面上較為流行的頭戴式 VR 一體機(jī),具備較好的性能,在這個(gè)部分,我們將介紹如何利用 Unity 進(jìn)行 Pico Neo 的應(yīng)用開發(fā)。
??Pico Neo 硬件部分主要包括頭盔和操作手柄,在進(jìn)行開發(fā)時(shí)我們需要熟悉一下硬件部分的使用。
??通過(guò)長(zhǎng)按頭盔的電源鍵的方式我們可以打開頭盔,打開頭盔后,通過(guò)按下手柄的 HOME 鍵連接手柄。

??在利用頭戴式顯示設(shè)備開發(fā)前,需要先了解一下相應(yīng)的游戲引擎。目前市面上有很多優(yōu)秀的商用游戲引擎和免費(fèi)游戲引擎,其中最具代表性的商用游戲引擎有 Unreal 和 Unity。
??Unity 是由 Unity Technologies 公司開發(fā)的跨平臺(tái)專業(yè)游戲引擎,用戶可以通過(guò)它輕松實(shí)現(xiàn)諸如 3D 游戲、建筑可視化、實(shí)時(shí)三維動(dòng)畫等類型互動(dòng)內(nèi)容,然后一鍵部署到各種游戲平臺(tái)上。
??Unity 以其強(qiáng)大的跨平臺(tái)特性與優(yōu)秀的 3D 渲染效果而深受廣大開發(fā)者的青睞,現(xiàn)在很多商業(yè)游戲及虛擬現(xiàn)實(shí)產(chǎn)品都采用 Unity 引擎來(lái)開發(fā)。
??Unreal 是 Unreal Engine 的簡(jiǎn)寫,中文名為虛幻,由 Epic 開發(fā),是世界知名授權(quán)最廣的游戲引擎之一。Unreal Engine 是全球最開放、最先進(jìn)的實(shí)時(shí) 3D 創(chuàng)建工具,可制作照片級(jí)逼真的視覺效果和沉浸式體驗(yàn)。
??虛幻引擎是一套完整的開發(fā)工具,面向所有使用實(shí)時(shí)技術(shù)的開發(fā)者。它能為各行各業(yè)的專業(yè)人士帶去無(wú)限的創(chuàng)作自由和空前的掌控力。無(wú)論是前沿娛樂(lè)內(nèi)容、精美的可視化還是沉浸式虛擬世界,一切盡在虛擬引擎。
2.軟件配置
??由于 Pico Neo 是基于 Android 平臺(tái)的,因此開發(fā)者在利用 Unity 進(jìn)行開發(fā)時(shí),需要在 Unity 中添加相應(yīng)的 Android 平臺(tái)的支持模塊。如果安裝 Unity 時(shí)沒(méi)有安裝,可以在 Unity Hub 中進(jìn)行相應(yīng)模塊的添加。
??在 Unity Hub 中點(diǎn)擊進(jìn)入安裝界面,選擇相對(duì)應(yīng)的 Unity 編輯器,點(diǎn)擊其左上方的更多按鈕,在界面中選擇添加模塊。

??在添加模塊界面選擇Android Build Support模塊并安裝。

??利用搜索引擎搜索 Pico 找到相應(yīng)頁(yè)面的方式或者直接通過(guò)網(wǎng)址 https://www.pico-interactive.com/cn/,直接進(jìn)入 Pico 的官方網(wǎng)站。點(diǎn)擊網(wǎng)站上方的開發(fā)平臺(tái)進(jìn)入 Pico 開發(fā)者平臺(tái)。

??在 Pico 開發(fā)者平臺(tái)頁(yè)面點(diǎn)擊下載 SDK,進(jìn)入 SDK 界面,如下圖所示。

??在下載 SDK 界面中選擇開發(fā)所采用的 Pico Neo 2 series 以及相對(duì)應(yīng)的開發(fā)平臺(tái) Unity。選擇好相應(yīng)的事項(xiàng),點(diǎn)擊頁(yè)面下方的下載最新版進(jìn)行 SDK 下載。

??在 Unity Hub 中新建一個(gè) Unity 工程,新建工程完成后,選擇 Assets 菜單中的 Import Package 點(diǎn)擊 Custom Package。

??點(diǎn)擊 Custom Package 后,在彈出的文件資源管理器中,選擇下載好的 PicoVR Unity SDK。SDK 有 32bit 和 64bit 兩個(gè)版本,開發(fā)者根據(jù)自身設(shè)備選擇相應(yīng)版本。

??點(diǎn)擊打開后,系統(tǒng)會(huì)彈出一個(gè)對(duì)話框,開發(fā)者可以根據(jù)需要導(dǎo)入相應(yīng)的部分,如下圖所示。

??等待 SDK 導(dǎo)入完成,在彈出的 Pico SDK Setting 窗口,修改相應(yīng)的設(shè)置,修改完成后點(diǎn)擊下方的 “Apply” 后,關(guān)閉窗口。

3.演示示例
??在 Unity 的 Asset Store 搜索 “POLYGON Starter Pack” 點(diǎn)擊Import將資源包導(dǎo)入項(xiàng)目。

??找到資源包中的場(chǎng)景文件,雙擊進(jìn)入資源包中的場(chǎng)景。

??進(jìn)入 Project 選項(xiàng)卡,依次展開 Assets 中的 PicoMobileSDK,找到Pvr_UnitySDK,打開 Pvr_Unity 文件夾選擇其中的 Prefabs,將 Pvr_UnitySDK 預(yù)制體拖放入場(chǎng)景。

??Pvr_UnitySDK 是一個(gè)集成式的預(yù)制體,能夠跟蹤頭戴式顯示器,在創(chuàng)建項(xiàng)目時(shí),可以直接將 Pvr_UnitySDK 預(yù)制體拖放至場(chǎng)景中。
??將原場(chǎng)景中的攝像機(jī)刪除,并調(diào)整好 Pvr_UnitySDK 的位置。調(diào)整好位置后,點(diǎn)擊運(yùn)行可以查看場(chǎng)景的雙目視圖預(yù)覽。

??開發(fā)者可以通過(guò)鍵盤上的 Alt 鍵和鼠標(biāo)左鍵進(jìn)行運(yùn)行視圖的切換,開發(fā)者根據(jù)自身需要可以選擇視圖在 Game 面板的呈現(xiàn)方式,也即雙目視圖和單目全屏之間的切換。通過(guò)鍵盤上 Alt 鍵和鼠標(biāo)的移動(dòng),開發(fā)者可以改變相機(jī)的朝向,以此查看場(chǎng)景。
??接著找到 Assets 下的 Pvr_Controller 中的 Prefabs,選擇其中的 ControllerManager,如下圖所示。

??ControllerManager 主要包含 PvrController0 和 PvrController1,這兩個(gè)預(yù)制體主要對(duì)應(yīng)于兩個(gè)手柄。對(duì)于部分單手柄的設(shè)備,可以只使用其中的 PvrController0。將 ControllerManager 預(yù)制體拖放至 Pvr_UnitySDK 下,作為 Pvr_UnitySDK 的子物體。

??拖放完成后,點(diǎn)擊運(yùn)行。在 Game 視圖中,可以看到兩個(gè)白色透明手柄的模型。

??顯示手柄后,我們需要利用手柄與場(chǎng)景進(jìn)行交互,使用操作手柄的按鍵與搖桿之前需要了解手柄的相應(yīng)按鍵的作用,以及對(duì)應(yīng)的接口 API。操作手柄主要包含 HOME 鍵、操作鍵、搖桿、側(cè)按鍵以及扳機(jī)鍵,這些鍵在不同應(yīng)用中常對(duì)應(yīng)著不同的功能。在開發(fā)過(guò)程中,我們根據(jù)需求自定義按鍵對(duì)應(yīng)的功能,并為此編寫相應(yīng)的響應(yīng)事件處理程序,來(lái)實(shí)現(xiàn)手柄按鍵與應(yīng)用的交互。

??在應(yīng)用開發(fā)時(shí),我們常常需要根據(jù)手柄的接口 API,對(duì)手柄的按鍵進(jìn)行配置,利用接口 API 實(shí)現(xiàn)相應(yīng)的交互,例如響應(yīng)手柄按下事件等。下表即為 Pico Neo 不同按鍵對(duì)應(yīng)的輸入事件。
| 按鍵 | 輸入事件 |
|---|---|
| HOME鍵 | Pvr_KeyCode.HOME |
| APP返回鍵 | Pvr_KeyCode.APP |
| 扳機(jī)鍵 | Pvr_KeyCode.TRIGGER |
| 側(cè)按鍵 | Pvr_KeyCode.Right(手柄1為Right) |
| Pvr_KeyCode.Left(手柄0為left) | |
| 搖桿 | Pvr_KeyCode.TOUCHPAD |
| X鍵 | Pvr_KeyCode.X(手柄0) |
| Y鍵 | Pvr_KeyCode.Y(手柄0) |
| A鍵 | Pvr_KeyCode.A(手柄1) |
| B鍵 | Pvr_KeyCode.B(手柄1) |
??通過(guò)將按鍵對(duì)應(yīng)的輸入事件與 API 接口函數(shù)相結(jié)合使用,即可通過(guò)腳本獲取手柄的交互信息。
??通過(guò) UPvr_GetControllerState 函數(shù)能夠獲取 Controller 連接狀態(tài),可以用來(lái)判斷手柄控制器是否連接并且能夠使用。

??結(jié)合上圖中 UPvr_GetControllerState 函數(shù)的定義,我們可以發(fā)現(xiàn)函數(shù)的返回值為 ControllerState 類型,ControllerState 為枚舉類型,包含三種狀態(tài),Connected 即為連接成功。

??同樣的,我們可以利用 UPvr_GetKey 函數(shù)獲取手柄控制器的按鍵是否被按住,UPvr_GetKey 函數(shù)如下所示。在調(diào)用函數(shù)時(shí),我們需要指定手柄控制器(hand),以及需要檢測(cè)的按鍵(key)。通過(guò)函數(shù)的返回值我們可以知道相應(yīng)的按鍵是否被按住,按鍵被按住即返回 true,按鍵未按住即返回 false。

??介紹了上述接口函數(shù),我們?cè)陧?xiàng)目中新建文件夾,并命名為 Scripts,在 Scripts 文件夾中新建腳本并命名為 ControllerDemo。利用這個(gè)腳本演示相應(yīng)函數(shù)的使用。

??雙擊打開腳本,在腳本中添加相應(yīng)的檢測(cè)代碼如下所示。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Pvr_UnitySDKAPI;
public class PicoControllerDemo : MonoBehaviour
{
void Update()
{
if(Controller.UPvr_GetControllerState(0) == ControllerState.Connected)
if(Controller.UPvr_GetKey(0, Pvr_KeyCode.TRIGGER))
Debug.Log("正在按Trigger鍵!");
}
}
??在腳本中,我們?cè)趇f條件語(yǔ)句的判斷條件中填入表達(dá)式,利用 UPvr_GetControllerState 判斷 PvrController0 是否接入成功。如果接入成功,再利用 if 語(yǔ)句結(jié)合 UPvr_GetKey 判斷指定手柄控制器的 Trigger 鍵是否被按住。
??相應(yīng)的函數(shù)調(diào)用時(shí)通過(guò)傳入 0/1 的方式來(lái)指定函數(shù)判斷相應(yīng)手柄控制器,根據(jù)傳入的相應(yīng)按鍵判斷按鍵是否被按下。
??在 API 函數(shù)中,還用兩個(gè)函數(shù) UPvr_GetKeyDown、UPvr_GetKeyUp 來(lái)判斷按鍵的狀態(tài)。UPvr_GetKeyDown 函數(shù)可以判斷按鍵是否被按下,UPvr_GetKeyUp 可以用來(lái)判斷按鍵是否被抬起。

??這兩個(gè)函數(shù)和前面介紹的函數(shù)類似,傳入?yún)?shù)為 hand 和 key,這兩個(gè)參數(shù)即為指定手柄控制器和手柄控制器的按鍵。
??Pico Neo 2 的手柄控制器中包含搖桿鍵,對(duì)于搖桿不能和其他按鍵一樣。搖桿與觸摸板類似,撥動(dòng)搖桿的值和觸摸板的值類似。在早期版本中,獲取觸摸板的主要利用 UPvr_GetTouchPadPosition 函數(shù)獲取觸摸板的 touch 值。后來(lái),觸摸板和搖桿樣式的操作手柄進(jìn)行統(tǒng)一,統(tǒng)一利用 UPvr_GetAxis2D 函數(shù)。

??在觸摸板上,以觸摸板的中心為坐標(biāo)中心,建立一個(gè) -1 到 1 的兩個(gè)坐標(biāo)軸,手指觸摸觸摸板的相應(yīng)位置,坐標(biāo)軸能夠得到相應(yīng)的觸摸位置。搖桿也可以和觸摸板一樣,利用類似的原理,可以獲取搖桿的撥動(dòng)值,如下圖所示。

??在 API 函數(shù)中,可以利用 UPvr_GetAxis2D 函數(shù),獲取搖桿的撥動(dòng)值。UPvr_GetAxis2D 函數(shù)需要傳入 hand,也即指明操作手柄。UPvr_GetAxis2D 函數(shù)的返回值為二維向量(Vector2),返回值的范圍為 -1 到 1。

??Pico 一體機(jī)除了手柄按鍵,頭戴式顯示器上也有相應(yīng)的按鍵。下表列出了一體機(jī)頭戴式顯示器上的常用按鍵與 Unity 里的鍵值對(duì)應(yīng)關(guān)系。
| HMD按鍵 | Unity輸入鍵 |
|---|---|
| 返回值 | KeyCode.Escape |
| 確認(rèn)值 | KeyCode.JoystickButton0 |
??頭戴式顯示器同手柄控制器按鍵類似,可以使用相應(yīng)的同手柄按鍵類似的 API 接口函數(shù),檢測(cè)頭戴式顯示器上的按鍵狀態(tài)。
??需要注意的是,頭戴式顯示器的按鍵與操作手柄的按鍵的接口 API 函數(shù)使用存在不同,操作手柄的 API 接口函數(shù)的調(diào)用需要使用 Controller,對(duì)于頭戴式顯示器的按鍵的使用是通過(guò) Input 輸入系統(tǒng)。
??類似的,我們可以編寫腳本結(jié)合 if 判斷語(yǔ)句判斷相應(yīng)的按鍵的使用情況,對(duì)于相應(yīng)的按鍵可以按照按鍵對(duì)應(yīng)的事件的對(duì)照表指定相應(yīng)的按鍵。
if(Input.GetKeyDown(KeyCode.Joystick1Button0))
{
Debug.Log(“頭戴式顯示器確認(rèn)鍵被按下!”);
}
??在腳本中編寫相應(yīng)的內(nèi)容后,將腳本掛載到游戲場(chǎng)景中的物體上,由于腳本內(nèi)容需要和手柄控制器進(jìn)行交互。因此編寫完成相應(yīng)的腳本后,需要結(jié)合設(shè)備進(jìn)行相應(yīng)的調(diào)試,腳本的完整內(nèi)容如下所示。
public class ControllerDemo : MonoBehaviour
{
void Update()
{
if (Controller.UPvr_GetControllerState(0) == ControllerState.Connected)
{
if (Controller.UPvr_GetKey(0, Pvr_KeyCode.TRIGGER))
Debug.Log("正在按Trigger鍵!");
if (Controller.UPvr_GetKeyDown(0, Pvr_KeyCode.TRIGGER))
Debug.Log("Trigger鍵被按下!");
if (Controller.UPvr_GetKeyUp(0, Pvr_KeyCode.TRIGGER))
Debug.Log("Trigger鍵被松開!");
Vector2 DialValue = Controller.UPvr_GetAxis2D(0);
Debug.Log("搖桿的撥動(dòng)值:" + DialValue);
}
if (Input.GetKeyDown(KeyCode.Joystick1Button0))
Debug.Log("頭戴式顯示器確認(rèn)鍵被按下!");
}
}
??在進(jìn)行調(diào)試時(shí),需要事先對(duì)項(xiàng)目進(jìn)行打包。在 Unity 編輯器中,通過(guò) Unity 上方菜單欄中的 File 下的 Build Settings 進(jìn)入項(xiàng)目打包界面。

??通過(guò) Build Settings 進(jìn)入項(xiàng)目打包界面后,點(diǎn)擊界面上 “Add Open Scenes”,添加當(dāng)前場(chǎng)景進(jìn)入打包列表。在下方的 Platform 中選擇 Android,點(diǎn)擊界面的左下角的 “Player Settings” 進(jìn)入玩家設(shè)置界面。

??在 Player Settings 界面中,選擇 Other Settings,在 Other Settings 界面中修改 PackageName,同時(shí) Minimum API Level 和 Target API Level 選擇相對(duì)應(yīng)版本的 API level。

??將頭戴式顯示器與電腦上處于同一個(gè)局域網(wǎng)下或者通過(guò)數(shù)據(jù)線將設(shè)備與電腦進(jìn)行連接,等待設(shè)備接入完成后,在 Build Settings 界面中點(diǎn)擊 “Refresh”。刷新完成后,在 Run Device 中添加 Pico Neo 2 即可指定運(yùn)行設(shè)備。

??修改完相應(yīng)設(shè)置后,點(diǎn)擊界面右下角的 “Build And Run”(也可以點(diǎn)擊 Build 后續(xù)再在 Pico 設(shè)備中點(diǎn)擊運(yùn)行),在彈出來(lái)的文件資源管理器中新建文件夾 AndroidPackage 并將打包好的 apk 文件命名后存入指定的文件夾。
