UNITY虛擬實境控制(一){VR視線焦點計時觸發事件}

一般來說手機類型的VR遊戲模式,如果不連接上手把控制器,除了少部分手機支援Cardboard旁邊的磁力板機外,最基本的操控方式就是以視覺中心來當作觸發條件,因為我們唯一能控制的就是頭的旋轉(陀螺儀水平儀),本篇就試著用射線來實現,焦點計時觸發的功能。

googlecardboard

(上圖側邊的鐵環就是磁力板機)

1.首先準備一個簡易場景,把攝影機置中並稍微離開地面(將Y設為2)
,這點稍微有點重要性,攝影機的位置在世界中心便於GoogleVR控制(主要原因是啟動後預設將攝影機放置世界中心當起點),避免射線起始發射的位置有偏差最好讓起始點重合。unet-hit-093

2.接下來建立我們的3D UI Canvas重新命名為FocusCanvas並調整RenderMode為WorldSpace
unet-hit-094
隨後調整RectTransform的原始座標Pos的XY都先將他歸零Z些微增加放置攝影機前確保可以看見,並調整UI的寬高250確保清晰
unet-hit-095

3.接下來用PS(PhotoShop)準備我們的UI素材,一個計時進度用的圓圈,製作時用128或256正方白色即可,用白色可以方便日後染色改變。
unet-hit-096

4.再加入Image和Text的UI到Canvas下
unet-hit-097並且做全版撐開的設定讓大小的控制交由外層的Canvas
unet-hit-098

5.調整Image和Text的內容如下:
unet-hit-099
將做好的圖片轉成Sprite格式放入SourceImage、調整顏色、Type改成Filled。
unet-hit-100
文字部分可以先清空,調整適中的大小、Alignment對齊置中、變更顏色。為了文字不被遮蔽順便將TOP屬性-300至於圓圈上方(位置可以自行調整),看起來會像這樣:

unet-hit-101

6.由於是3D的UI,希望她能跟著攝影機移動直接將它塞入MainCamera下並且使用標準單位1的CUBE對照下UI的大小尺寸比例,然後調整Canvas的縮放(目的是為了算出物件和UI之間的比例關係)unet-hit-102
unet-hit-103
大約是0.01的XY縮放比例,Z可以保持不變。

7.接下來撰寫程式RayGun.cs掛載於主攝影機上

首先宣告放Canvas的GameObject以及底下的Image、Text的public欄位,還有計時用的float、要打出射線的Camera本體以及被擊中的物體,並且在Start初始化攝影機本身並且讓UI Image的fillAmount初始化為0,=focusTimer計時用的浮點數。

8.接下來將Update改為FixedUpdate在裡面增加射線的程式碼

首先Ray的條件是透過兩個點畫出一條線的概念執行,所以言下之意我們需要兩個座標。一個是由攝影機的位置發出,那目標點呢?這部分比較複雜些,應該視攝影機前方一段距離的一個延伸,也就是她是一個不斷在改變的座標位置,所以我們透過攝影機的ScreenToWorldPoint取得螢幕正中央的XY座標然後把Z指定一個長度(這裡使用200),取得螢幕正前方遠處的一個虛擬的座標位置把設線產生,透過Debug.DrawLine我們可以在畫面上看到這條畫出的射線。
unet-hit-104

9.由於這條射線可以可以產生碰撞偵測的,透過Physics.Raycast物理的射線投放導出碰撞的物體

可以放置一個帶有MONSTER標籤的Cube測試看看可否印出他的名子

10.接下來就可以寫一個FocusDo方法來執行想做的事情

執行時檢查是否有打擊到物體,有的話將UI的位置移動到該物體上,並透過引數O檢查我們的計時UI跑滿了沒有(大於等於1)就銷毀該物件。

11.FocusDo方法的引數O自然需要另個帶回傳值的方法計數器來輔助

FocusTimer的引數f用來決定計時器跑得快慢,數字越大增加的越快,而且可以使用文字輔助知道這次要多少時間,假設沒有打到物體時帶入0就可以淨空計時器和文字。不斷刷新環形UI百分比(focus.fillAmount = focusTimer),並回傳focusTimer讓FocusDo知道何時可以摧毀該物體。

12.最後補完打擊到MONSTER的方法條件可以得到如下效果:
unet-hit-105完整程式:

 

Leave a Reply