此教程相關(guān)的詳細(xì)教案,文檔,思維導(dǎo)圖和工程文件會(huì)放入 Spatial XR 社區(qū)。這是一個(gè)高質(zhì)量知識(shí)星球 XR 社區(qū),博主目前在內(nèi)擔(dān)任 XR 開發(fā)的講師。此外,該社區(qū)提供教程答疑、及時(shí)交流、進(jìn)階教程、外包、行業(yè)動(dòng)態(tài)等服務(wù)。
社區(qū)鏈接:
Spatial XR 高級(jí)社區(qū)(知識(shí)星球)
Spatial XR 高級(jí)社區(qū)(愛發(fā)電)
往期回顧:
Unity VR 開發(fā)教程 OpenXR+XR Interaction Toolkit (一) 安裝和配置
Unity VR 開發(fā)教程 OpenXR+XR Interaction Toolkit (二) 手部動(dòng)畫
Unity VR 開發(fā)教程 OpenXR+XR Interaction Toolkit (三) 轉(zhuǎn)向和移動(dòng)
Unity VR 開發(fā)教程 OpenXR+XR Interaction Toolkit (四) 傳送
在 VR 的交互中,與 UI 進(jìn)行交互是很常見的功能。本篇教程,我將介紹如何在 VR 世界中用射線進(jìn)行 UI 的交互。
??教程說明
使用的 Unity 版本: 2021.3.5
使用的 VR 頭顯: Oculus Quest 2
教程使用的 XR Interaction Toolkit 版本:2.3.2(此教程盡量考慮了向上兼容,如果有過期的地方,歡迎大家指出)
項(xiàng)目源碼(持續(xù)更新):https://github.com/YY-nb/Unity_XRInteractionToolkit2.3.2_Demo
前期的配置:環(huán)境配置參考教程一,手部模型參考教程二。本篇教程的場(chǎng)景基于上一篇教程搭建的場(chǎng)景進(jìn)行延伸。
最終實(shí)現(xiàn)的效果:手部射線(一開始是看不見的)對(duì)準(zhǔn) UI 時(shí),會(huì)顯示一條指向 UI 的射線。按下手柄的 Trigger 鍵,能與可交互的 UI(如 Button,Toggle,Slider 等)進(jìn)行互動(dòng)。
??制作 World Space 模式的 UI
首先在場(chǎng)景中創(chuàng)建一個(gè) Canvas 游戲物體?;?VR 應(yīng)用的沉浸感,其中的 UI 應(yīng)該是 3D 世界中的一部分,因此我們?cè)谥谱?UI 的時(shí)候要把 Canvas 組件的 Render Mode 改為 World Space
然后調(diào)整一下 Canvas 的大小和位置,就可以在 Canvas 上添加 UI 了。這里我就加上一個(gè) Button,一個(gè) Toggle 和 一個(gè) Slider:
??添加 Tracked Device Graphic Raycaster 腳本
把 Canvas 上原來的 Graphic Raycaster 組件刪掉,添加 Tracked Device Graphic Raycaster 腳本。添加了這個(gè)腳本后,UI 就能被射線響應(yīng),比如被射線選中高亮。
??添加 XR UI Input Module 腳本
在 EventSystem 游戲物體上添加 XR UI Input Module 腳本,并且把原先的 Standalone Input Module 腳本移除。XR UI Input Module 配合 Event System 組件,可以讓 Input Action 中的動(dòng)作配置作用于 VR 中的 UI,也可以用于 PC 端的鍵鼠調(diào)試,總的來說就是結(jié)合了 Input System,用于管理 XR 中 UI 的相關(guān)輸入。
??添加 UI 射線相關(guān)腳本
因?yàn)樵谖覀兊男枨笾?,是用射線與 UI 進(jìn)行交互,所以我們需要添加和射線相關(guān)的腳本。這時(shí)候我們可以聯(lián)想一下我寫的上一篇傳送教程(Unity VR開發(fā)教程 OpenXR+XR Interaction Toolkit (四) 傳送)。因?yàn)閭魉鸵灿杏玫缴渚€,所以我們完全可以用類似的思路實(shí)現(xiàn) UI 射線,即分別在左右手的控制器上添加發(fā)送射線的相關(guān)腳本。
?負(fù)責(zé) UI 射線的物體和掛載的腳本
我們沿用上一篇傳送教程中的 XR Origin (因此保留了傳送功能),然后分別在 LeftHand Controller 和 RightHandController 下創(chuàng)建 UI Ray Interactor 游戲物體:
模仿傳送功能,在 UI Ray Interactor 物體添加上 XR Ray Interactor(Line Type 為 Straight Line,因?yàn)槲覀兿M?UI 的射線是一條直線),Line Renderer(可以復(fù)制 TeleportController 上的 Line Renderer 組件),XR Interactor Line Visual 腳本,Sorting Group 組件(不添加該組件也能實(shí)現(xiàn)功能,不過官方添加 XR Ray Interactor 的時(shí)候會(huì)附帶一個(gè) Sorting Group,下面也會(huì)介紹一下 Sorting Group 的作用)。
左右手都添加了這些組件后,就能夠發(fā)射一條直的射線。我們可以運(yùn)行一下程序,這時(shí)候會(huì)發(fā)現(xiàn)兩只手都會(huì)射出一條直的射線,當(dāng)射線射到 UI 上時(shí),按下手柄的 Trigger 鍵能被可交互的 UI (Button,Toggle,Slider)響應(yīng),比如能用射線點(diǎn)擊按鈕,拖動(dòng)滑動(dòng)條。
?為什么控制 UI 射線的物體不用添加 XR Controller
這里有些小伙伴可能會(huì)有疑問,為什么 UI Ray Interactor 不用添加 XR Controller 腳本呢?而上一篇傳送教程中控制傳送射線的 Teleport Interactor 物體卻添加了 XR Controller 腳本,還把其中的 Enable Input Tracking 給關(guān)閉了。
我們可以看 UI Ray Interactor 的父物體 LeftHand Controller 或 RightHand Controller,在父物體上已經(jīng)有了 XR Controller:
因?yàn)楦肝矬w XR Controller 面板上的這些 Action 同樣適用于 UI 射線操作,所以我們只需要讓父物體的 XR Controller 處理輸入,作為子物體的 UI Ray Interactor 無需添加額外的 XR Controller。這時(shí)候子物體的 Input Action 就會(huì)沿用父物體 XR Controller 中設(shè)置的那些 Action。
而在傳送功能中,作為子物體的 Teleport Interactor 需要添加 XR Controller,是因?yàn)閭魉偷?Select Action 和父物體的 Select Action 不一樣(見下圖) ,所以我們需要在子物體上額外添加一個(gè) XR Controller,并且將 Enable Input Tracking 關(guān)閉防止追蹤的沖突。
作為父物體的 LeftHand Controller:
作為子物體的 Teleport Interactor:
?Sorting Group 的作用
下面這段是官方文檔的版本變更日志中的介紹:
Changed the Ray Interactor GameObject created through the GameObject > XR create menu to have a Sorting Group to make it render in front of UI
在創(chuàng)建擁有 XR Ray Interactor 的物體時(shí),會(huì)默認(rèn)添加一個(gè) Sorting Group 組件。這個(gè)組件是 Unity UGUI 中的一個(gè)組件,每個(gè)參數(shù)具體什么意思可以查看官方文檔。通過控制該組件上的參數(shù),能夠控制 UI 射線渲染在 UI 之前。
我這里就演示其中一種用法,比如我可以將 Sorting Group 的 Order in Layer 設(shè)為 5:
然后找到場(chǎng)景中的 Canvas 物體 的 Canvas 組件:
只要 Canvas 組件中的 Order in Layer 小于或等于 Sorting Group 中的 Order in Layer, UI 射線就會(huì)始終渲染在 UI 的前面。大家可以自行設(shè)置兩個(gè) Order in Layer 的值感受一下,如果 Canvas 組件中的 Order in Layer 大于 Sorting Group 中的 Order in Layer,那么我們是看不到 UI 射線的。
不過,即使沒有添加 Sorting Group 組件,UI 射線也是會(huì)渲染在 UI 之前,只不過這個(gè)組件給了我們自定義的功能。是否需要添加這個(gè)組件就看大家的需求了。
??過濾 UI 射線的目標(biāo)
但是仍然存在一個(gè)問題,我們的 XR Interactor Line Visual 腳本規(guī)定了當(dāng) UI 射線被激活時(shí),射線顏色為白色;未被激活時(shí)射線顏色為紅色。見 XR Interactor Line Visual 的 Valid Color Gradient 和 Invalid Color Gradient:
但是當(dāng)我們的 UI 射線射在地面上的時(shí)候仍然處于激活的狀態(tài),還會(huì)顯示傳送功能中射線末端的 Reticle,并且當(dāng)我們按下手柄的 Grip 鍵,居然也會(huì)觸發(fā)傳送。(見下圖,UI 射線射到地面上時(shí)顏色為白色,說明處于激活的狀態(tài))
這個(gè)問題其實(shí)和上一篇傳送教程中出現(xiàn)的問題是一樣的,此時(shí)我們擁有兩種射線,一種是傳送射線,被上一篇教程中我們自己寫的 TeleportationController 腳本所控制;另一種是剛剛創(chuàng)建的 UI 射線,它使用的是默認(rèn)的配置。
因?yàn)槲覀冎敖o地面添加了 Teleportation Area 腳本,默認(rèn)情況下是當(dāng)射線射到地面的碰撞體時(shí),會(huì)視為選中了傳送區(qū)域,然后因?yàn)樨?fù)責(zé) UI 射線的 XR Controller 中的 Select Action 默認(rèn)綁定的是 XRI LeftHand/RightHand Interaction 下的 Select 動(dòng)作,而 Select 動(dòng)作又綁定了 “Grip 鍵按下” 這個(gè)操作,所以按下 Grip 鍵會(huì)響應(yīng)到傳送的功能。而且是本應(yīng)該負(fù)責(zé)與 UI 交互的射線響應(yīng)了傳送的觸發(fā)。
但我們希望的是 UI 射線只有射到 UI 上的時(shí)候才能被激活。所以我們要對(duì)能激活 UI 射線的目標(biāo)做個(gè)過濾。解決辦法也很簡(jiǎn)單,我們找到 LeftHand UIController 物體和 RightHand UIController 物體上掛載的 XR Ray Interactor 腳本,把 Raycast Mask 中的 Everything 改成 UI :
修改前:
修改后:
現(xiàn)在我們?cè)龠\(yùn)行一下程序,這時(shí)候 UI 射線只有射到 UI 上才會(huì)變成白色,而射到地面上顯示的是紅色,說明只有 UI 激活了 UI 射線。
但是這里還可以有個(gè)優(yōu)化,在當(dāng)前的程序中,我們會(huì)看到手部一直射出一條有顏色的射線,即使沒有指向 UI,場(chǎng)景中依然存在一條紅色的射線。而我們可以這樣改進(jìn):讓射線射到 UI 上時(shí)才能顯示,而射到其他地方不顯示射線。
??使射線射到 UI 上時(shí)才顯示射線顏色
改進(jìn)方法很簡(jiǎn)單,找到 XR Interactor Line Visual 腳本,修改 Invalid Color Gradient,我們可以把它的透明度改為 0。這樣,當(dāng)射線射到不是 UI 的地方時(shí),射線就是透明的,在我們的眼中就是不顯示的。
點(diǎn)開 Invalid Color Gradient 后,找到左上角和右上角白色的角標(biāo),點(diǎn)擊后找到 Alpha 值,將它改成 0 就能讓射線在未激活狀態(tài)下處于透明狀態(tài)。
修改前:
修改后:
現(xiàn)在再次運(yùn)行程序,這時(shí)候只有射線射到 UI 上的時(shí)候才會(huì)看到白色的射線。
??改變射線發(fā)射的位置
現(xiàn)在我們的射線是從大拇指附近射出來的,但是如果我想改變射線發(fā)射的位置呢?
其實(shí)操作也很簡(jiǎn)單,我們?cè)谑植磕P拖聞?chuàng)建一個(gè)子物體作為射線發(fā)射的起始點(diǎn),我這里將起始點(diǎn)的位置移至食指的地方,相當(dāng)于讓射線從食指處發(fā)出,射線發(fā)射的方向與起始點(diǎn)本地坐標(biāo)的 z 軸方向一致。
找到 XR Ray Interactor 腳本中的 Ray Origin Transform
然后將剛剛創(chuàng)建的射線起始點(diǎn)分別拖入對(duì)應(yīng)的 XR Ray Interactor 腳本的 Ray Origin Transform
現(xiàn)在試著運(yùn)行程序,射線就會(huì)從食指射出啦!??
??通過按下手柄菜單鍵控制 UI 的顯示與隱藏
最近有好多小伙伴問我如何實(shí)現(xiàn)通過按下 VR 手柄的菜單鍵(一般位于左手柄上)來控制 UI 的顯示和隱藏,那么我這里就介紹一種簡(jiǎn)單的做法。
?添加 Action
首先我們要在 XRI Default Input Actions 中配置按下手柄菜單鍵的 Action:
然后在 XRI LeftHand 中點(diǎn)擊下圖所示的 “+” 號(hào),會(huì)新增一個(gè) Action,我們把它命名為 Menu
確保右側(cè)面板的 Action Properties 中的 Action Type 為 Button,因?yàn)槲覀儥z測(cè)的是按鍵是否被按下。
接著點(diǎn)擊 Menu下方的這個(gè) Binding,點(diǎn)擊右側(cè)面板的 Path,選擇 XR Controller:
選擇 XR Controller (LeftHand):
選擇 Optional Controls:
選擇 menuButton:
最后別忘了點(diǎn)擊面板上方的 Save Asset 進(jìn)行保存:
?腳本控制
接下來,我們需要去得到剛剛配置的 Action,并且判斷 Action 是否被觸發(fā),我們可以寫個(gè)腳本來控制:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class UIController : MonoBehaviour
{
public InputActionReference menu;
public Canvas canvas;
private void Start()
{
if(menu != null)
{
menu.action.Enable();
menu.action.performed += ToggleMenu;
}
}
private void ToggleMenu(InputAction.CallbackContext context)
{
canvas.enabled = !canvas.enabled;
}
}
然后我把這個(gè)腳本掛載到 LeftHand Controller 物體上,并且將剛剛添加的 Menu 和場(chǎng)景中的 Canvas 拖拽到 面板中:
文章來源:http://www.zghlxwxcb.cn/news/detail-513818.html
現(xiàn)在運(yùn)行游戲,通過按下左手柄的菜單鍵就能夠控制 UI 的顯示和隱藏了。文章來源地址http://www.zghlxwxcb.cn/news/detail-513818.html
到了這里,關(guān)于Unity VR 開發(fā)教程 OpenXR+XR Interaction Toolkit (五) UI的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!