Unity - VR - 簡易畫面最上層UI顯示

  其實跟一般遊戲的顯示UI差不多,就只是在VR裡面呈現而已,所要呈現的目標就是當按下Menu按鈕或是遊戲系統跳出提示等等,這個時候會跳出一個UI介面面板,這個面板會在最上層顯示,不會被場景中的任何物件擋住。

  這邊用個還算簡單的方法來達到這麼目標,也就是用兩個Camera來照各自的物件即可,遊戲的Camera照場景Culling Mask排除UI物件,而UI Camera則只有照UI物件,排除其他物件。

  


  就如同畫面顯示的,這個UI有一塊黑色背景遮住場景,然後有一個面板顯示按鈕等等東西。
  


  從編輯器的另一個角度來看,就可以看到場景的方塊其實是在最前面,黑色面板跟按鈕面板都在後面,但是UI卻不會被場景物件擋住,就是因為Camera的Depth不同。




  首先需要匯入幾個免費的Plugin
  SteamVR Plugin (https://www.assetstore.unity3d.com/en/#!/content/32647)
  Vive Input Utility (https://www.assetstore.unity3d.com/en/#!/content/64219)
  VRTK (https://www.assetstore.unity3d.com/en/#!/content/64131)







  一開始先把SteamVR裡面的CameraRig拉到場景中,這時候額外建立一個Camera給UI使用,Culling Mask只選擇UI,然後Depth設定為0在眼睛Camera前面。






  眼睛的Camera設定Culling Mask去掉UI,Depth預設值應該是-1不需要改,不過還是看自己的需求去設定Depth。






  接著在Controller上面加上VRTK這個Plugin的Controller Event這個Component來取得控制器的事件。

  VivePointer在Vive Input Utility這個Plugin的Demo裡面可以找到,直接複製過來就好。






  接著做兩個簡單的UI面板,第一個是黑色背景,Render Mode選擇Screen Space - Camera,然後Camera就把剛剛的UI Camera拉進來設定就好。




  然後第二個UI Canvas來顯示按鈕或什麼3D面板之類的,Render Mode選擇World,同樣Event Camera選擇UI Camera,然後這個Order in Layer設定為1,因為前面那個黑色背景的Order in Layer是0,避免被黑色背景擋住所以這邊往前移動。

  這邊加了一個Canvas Raycast Target的Component來讓VR控制器去做碰撞。





  接下來做一個簡易的開啟Menu選單,的Component
public class Test: MonoBehaviour
{
    public GameObject[] ui; //所有UI面板
    private bool toggle = false;

    void Start()
    {
        //使用VRTK的Plugin並且using VRTK;這個Namespace
        if (GetComponent<VRTK_ControllerEvents>() == null)
        {
            this.enabled = false;
            return;
        }
        GetComponent<VRTK_ControllerEvents>().ApplicationMenuPressed += new ControllerInteractionEventHandler(DoApplicationMenuPressed);
        GetComponent<VRTK_ControllerEvents>().ApplicationMenuReleased += new ControllerInteractionEventHandler(DoApplicationMenuReleased);
    }

    void Update()
    {
    }

    private void DoApplicationMenuPressed(object sender, ControllerInteractionEventArgs e)
    {
    }

    //當按下放開Vive的Pad前方的Nemu按鈕
    private void DoApplicationMenuReleased(object sender, ControllerInteractionEventArgs e)
    {
        ToggleUI(!toggle);
    }

    public void ToggleUI(bool active)
    {
        foreach (GameObject go in ui)
            go.SetActive(active);
        toggle = active;
    }
}










  接著把這個Component隨便放到一個Controller上面,上面要有VRTK的Controller Events這個Component,然後把UI物件拉進去就完成了。










  測試後按下Menu按鈕打開UI,會發現控制器怎麼會被遮住了,因為剛剛控制器物件沒有設定Layer。



  這時候把控制器的Layer設定為UI,然後再測試一次看看。






  這次控制器的顯示就正常了,就不會被擋住了。但是有沒有發現一件事情,場景中的方塊竟然還是可以被RayCast判斷到(黃色球球)





  這邊可以打開VivePointers看裡面的EventRaycaster這個物件,看到這個Physic Raycast Method這個Component,可以在這邊做調整。



  這邊就不詳細說明怎麼調整了,可以比較偷懶一點就是當按下Menu打開選單的時候,這邊的Mask Exclusive排除的部分加入場景的Layer,例如Default,這樣打開Menu選單後,Raycast就不會對場景物件做判斷。

  然後關閉Menu的時候再把排除的Layer去掉Default,這時候又會對場景物件有Raycast的判斷了。




  到這邊就告一段落了,如果有任何問題或錯誤歡迎提出。

No comments:

Post a Comment