如何打開Unity對於VR的支持
在edit下拉菜單里,找到Project Setting選項,然后選擇Player,在Inspector中找到Other Setting,勾選Virtual Reality Supported復選框,即可獲取對於VR設備的支持。
點擊+號即可添加新的設備。目前,Unity支持的設備有oculus,openVR, Ste reo Display, Split Stereo Display。后面兩個是3D顯示器。
其中None的作用是可以在初始化的過程中,不進行VR頭顯的渲染,這樣可以讓同一個程序對多個設置進行支持。
下面我們來介紹下如何使用腳本來進行支持的SDK種類的切換。
- 我們首先把None類型放在最上方,OpenVR放在下方,其余支持的SDK刪除,如下圖所示:
- 現在我們運行程序,VIVE頭盔不會有任何反應,只會在電腦屏幕上出現畫面。
- 然后我們新建一個腳本ChangeVRType.cs
新建一個協程
IEnumerator LoadDevice(string newDevice)
{
yield return new WaitForSeconds(3.0f);
VRSettings.LoadDeviceByName(newDevice);
yield return null;
VRSettings.enabled = true;
}
為了以示區別,我們在更改支持的SDK前先等待3秒,在此時間內,只有電腦屏幕有畫面,3s過后,我們可以看到VIVE頭盔被激活。此時應注意在enable前,需等待一幀,否則會報錯。
相機設置
在添加了VR支持后,我們會發現在camera的Inspector面板中多出如圖2所示的幾個選項。
- stereo separation指的是瞳距(兩個虛擬眼睛之間的距離)
- stereo convergence指的是焦點
- target display指的是渲染的相機
- target eye指的是渲染的左右眼
Unity對手柄的支持
手柄的位置信息
InputTracking類可以用於獲取VR節點的位置和旋轉角度。其官方的解釋如下:
//
// Summary:
// ///
// VR Input tracking data.
// ///
public static class InputTracking
{
//
// Summary:
// ///
// The current position of the requested VRNode.
// ///
//
// Parameters:
// node:
// Node index.
//
// Returns:
// ///
// Position of node local to its tracking space.
// ///
public static Vector3 GetLocalPosition(VRNode node);
//
// Summary:
// ///
// The current rotation of the requested VRNode.
// ///
//
// Parameters:
// node:
// Node index.
//
// Returns:
// ///
// Rotation of node local to its tracking space.
// ///
public static Quaternion GetLocalRotation(VRNode node);
//
// Summary:
// ///
// Center tracking to the current position and orientation of the HMD.
// ///
public static void Recenter();
}
以下,我們通過一個簡單的示例來演示如何使用InputTracking類來模擬手柄。
- 新建兩個cude,一個命名為LeftHand,一個命名為RightHand. Cube的scale設為0.2。
- 然后新建一個empty game object,命名為Virtual man,作為手柄和相機的父物體。
- 把main camera和LeftHand, RightHand拖到Virtual man下面,並將其位置歸為0。
新建腳本RightHand.cs和LeftHand.cs,分別關聯到LeftHand, RightHand上。
在Update函數中寫:
this.transform.localPosition = InputTracking.GetLocalPosition(VRNode.RightHand);
this.transform.localRotation = InputTracking.GetLocalRotation(VRNode.RightHand);
LeftHand腳本中做出相應的替換即可。
運行程序,我們就可以看到手柄變成了兩個cube。
手柄的按鍵
HTC VIVE手柄的按鍵可以在Edit->Project Setting->Input中設定。
首先,我們需要找到HTC VIVE手柄對應的ID號,在unity的官網上可以找到其對應的信息:
https://docs.unity3d.com/Manual/OpenVRControllers.html
此時,我們就可以在Input里面設置手柄對應的按鍵了。我們以手柄上的trigger鍵為例,介紹如何使用手柄。
- 首先在InputManager中將Axes的數量加1.
- 將其名字命名為LCT.
- 按如圖所示的信息設置LCT的信息:
其中positive button對應即是上表中Unity Button ID中對應的值。
- 同理,我們在添加右手柄的trigger控制器。
- 我們在上述建立的腳本Lefthand.cs和Righthand.cs中加入以下控制語句:
if (Input.GetButton("LCT"))
{
Debug.Log("LCT");
}
if (Input.GetButton("RCT"))
{
Debug.Log("RCT");
}
- 運行程序,按下左右手的trigger鍵,即可在控制台打印相應的命令。
如果我們想獲得trigger按下去的程度的數值,則可以使用Squeeze類型。
具體做法如下:
- 首先在InputManager中將Axes的數量加1.
- 將其名字命名為LCT。
- 按如圖所示的信息設置LCT的信息:
與之前不同的地方是,Axis要改為9th axis,type要改為Joystick Axis類型。
- 在LeftHand.cs添加如下代碼:
float f1 = Input.GetAxis("LCT");
if (f1 > 0.1f)
{
Debug.Log(f1);
}
- 運行程序,按下trigger鍵,即可在控制台上獲取trigger鍵按下程度的大小。
- 同理,可以設置右手柄的trigger鍵。
此時,我們可以做一個射線放置到手柄上。
- 首先,我們以RightHand和LeftHand為父物體,各添加一個空物體。
- 然后在空物體上添加Line Renderer組件。
- 新建一個材質,將其shader改為Unlit/Color,並將其添加到Line Renderer上,這樣我們就可以更改射線的顏色。
- Line Renderer的設置信息參考如下:
- 我們在場景中新建一個UI組件,比如button。
- 將Canvas設置為World Space,調到合適的位置。
- 新建一個腳本ButtonClick.cs。在其中添加一個Do函數。
public void Do()
{
Debug.Log("Press the button");
}
- 將ButtonClick.cs添加到button上,並將Button上的OnClick組件設置為:
- 然后在LeftHand.cs腳本中加入以下語句:
Ray ray = new Ray(transform.position, transform.forward);
RaycastHit hit;
if (Input.GetButtonDown("LCT"))
{
if (Physics.Raycast(ray, out hit, 10000))
{
Debug.Log(hit.transform.name);
hit.transform.GetComponent<UnityEngine.UI.Button>().OnSubmit(new BaseEventData(EventSystem.current));
}
}
使用這種方法對於UI的通用性比較差,如果我們在添加toggle或是其他UI組件,就要重新的GetComponent,比較麻煩,為此,我們可以采取以下的做法。
- 首先,我們在場景中在新建一個UI toggle。然后在ButtonClick函數中添加如下的函數:
public void Do2()
{
Debug.Log("Press the toggle");
}
}
- 然后在toggle上的onClick()中添加如下:
- 然后在LeftHand.cs腳本中做如下的修改:
Ray ray = new Ray(transform.position, transform.forward);
RaycastHit hit;
if (Input.GetButtonDown("LCT"))
{
if (Physics.Raycast(ray, out hit, 10000))
{
Debug.Log(hit.transform.name);
// hit.transform.GetComponent<UnityEngine.UI.Button>().OnSubmit(new BaseEventData(EventSystem.current));
ExecuteEvents.Execute<ISubmitHandler>(hit.transform.gameObject, new BaseEventData(EventSystem.current), ExecuteEvents.submitHandler);
}
}
- 此時,不論是button還是toggle都可以正常運行。