Unity 中的手勢
在 Unity 中採取動作,在 HoloLens 和沈浸式 HMD 中,有兩個關鍵的方式可以採取動作。 您可以透過 Unity 中的相同 API 存取這兩個空間輸入來源的數據。
Unity 提供兩種主要方式來存取 Windows Mixed Reality 的空間輸入數據。 常見的 Input.GetButton/Input.GetAxis API 可跨多個 Unity XR SDK 運作,而 Windows Mixed Reality 專屬的 InteractionManager/GestureRecognizer API 則會公開完整的空間輸入數據集。
高階複合手勢 API (GestureRecognizer)
命名空間:UnityEngine.XR.WSA.Input
類型: GestureRecognizer、 GestureSettings、 InteractionSourceKind
您的應用程式也可以辨識空間輸入來源、點選、保留、操作和瀏覽手勢的高階複合手勢。 您可以使用 GestureRecognizer,跨雙手和運動控制器辨識這些複合手勢。
GestureRecognizer 上的每個 Gesture 事件都會提供輸入的 SourceKind,以及事件發生時的目標頭部光線。 某些事件會提供其他內容特定資訊。
使用手勢辨識器擷取手勢只需要幾個步驟:
- 建立新的手勢辨識器
- 指定要監看的手勢
- 訂閱這些手勢的事件
- 開始擷取手勢
建立新的手勢辨識器
若要使用 GestureRecognizer,您必須已建立 GestureRecognizer:
GestureRecognizer recognizer = new GestureRecognizer();
指定要監看的手勢
透過 SetRecognizableGestures 指定您感興趣的手勢:
recognizer.SetRecognizableGestures(GestureSettings.Tap | GestureSettings.Hold);
訂閱這些手勢的事件
訂閱您感興趣的手勢事件。
void Start()
{
recognizer.Tapped += GestureRecognizer_Tapped;
recognizer.HoldStarted += GestureRecognizer_HoldStarted;
recognizer.HoldCompleted += GestureRecognizer_HoldCompleted;
recognizer.HoldCanceled += GestureRecognizer_HoldCanceled;
}
注意
導覽和操作手勢在 GestureRecognizer 實例上互斥。
開始擷取手勢
根據預設,在呼叫 StartCapturingGestures() 之前,GestureRecognizer 不會監視輸入。 如果在處理 StopCapturingGestures() 的畫面之前執行輸入,可能會產生手勢事件。 GestureRecognizer 會記住它是否在先前發生手勢的畫面中開啟或關閉,因此根據此畫面的注視目標啟動和停止手勢監視是可靠的。
recognizer.StartCapturingGestures();
停止擷取手勢
若要停止手勢辨識:
recognizer.StopCapturingGestures();
拿掉手勢辨識器
請記得在終結 GestureRecognizer 物件之前,先取消訂閱訂閱的事件。
void OnDestroy()
{
recognizer.Tapped -= GestureRecognizer_Tapped;
recognizer.HoldStarted -= GestureRecognizer_HoldStarted;
recognizer.HoldCompleted -= GestureRecognizer_HoldCompleted;
recognizer.HoldCanceled -= GestureRecognizer_HoldCanceled;
}
在 Unity 中轉譯動作控制器模型
動作控制器模型和遠端傳送
若要在應用程式中轉譯符合使用者所持有之實體控制器的動作控制器,並在按下各種按鈕時清楚表達,您可以在混合實境工具組中使用MotionController預製專案。 這個預製專案會在運行時間從系統安裝的動作控制器驅動程式動態載入正確的 glTF 模型。 請務必以動態方式載入這些模型,而不是在編輯器中手動匯入這些模型,如此一來,您的應用程式就會針對使用者可能擁有的任何目前和未來的控制器顯示實際精確的 3D 模型。
- 請遵循用戶入門指示來下載混合實境工具組,並將其新增至您的 Unity 專案。
- 如果您將相機取代為 MixedRealityCameraParent 預製專案做為用戶入門步驟的一部分,您最好去! 該預製專案包含動作控制器轉譯。 否則,從 [專案] 窗格將 Assets/HoloToolkit/Input/Prefabs/MotionControllers.prefab 新增至場景。 您想要將預製專案新增為您在場景中用戶傳送時用來移動相機之父物件的子系,讓控制器隨附於使用者。 如果您的應用程式未涉及遠端傳送,只要在場景的根目錄新增預製專案即可。
擲回物件
在虛擬實境中擲回物件比一開始可能更困難的問題。 和大多數以物理為基礎的互動一樣,當扔進遊戲的行為出人意料的方式時,它立即明顯,並打破沉浸。 我們花了一些時間深入思考如何代表身體正確的擲回行為,並想出了一些指導方針,透過平臺的更新來啟用,我們想要與您分享。
您可以在這裡找到如何實作擲回的範例。 此範例遵循下列四個指導方針:
使用控制器 的速度 ,而不是位置。 在 Windows 的 11 月更新中,我們在「大約」位置追蹤狀態時,引進了行為變更。 處於這種狀態時,只要我們相信控制器的高精確度,控制器的速度資訊就會持續報告,這通常比位置更長,仍然具有高準確度。
併入控制器的角速度。 此邏輯全都包含在靜態方法的
GetThrownObjectVelAngVel
檔案中throwing.cs
,且在上方連結的套件中:由於角度速度受到保護,擲回的對象必須維持與擲回時相同的角度速度:
objectAngularVelocity = throwingControllerAngularVelocity;
由於擲回對象的品質中心可能不是位於夾板姿勢的原點,它的速度可能會與用戶參照框架中的控制器不同。 以這種方式貢獻的物件速度部分是控制器原點周圍被擲回物件品質中心的瞬間正切速度。 這個正切速度是控制器角度速度的交叉乘積,向量代表控制器原點與擲回物件品質中心之間的距離。
Vector3 radialVec = thrownObjectCenterOfMass - throwingControllerPos; Vector3 tangentialVelocity = Vector3.Cross(throwingControllerAngularVelocity, radialVec);
擲回物件的總速度是控制器的速度和這個正切速度的總和:
objectVelocity = throwingControllerVelocity + tangentialVelocity;
請密切關注我們套用速度的時間。 按下按鈕時,最多可能需要 20 毫秒的時間,該事件才會透過藍牙向操作系統泡泡。 這表示,如果您輪詢控制器狀態的變更,從按下變更為未按下或相反的方式,控制器會提供您取得的信息,實際上會領先於狀態的這項變更。 此外,我們輪詢 API 所呈現的控制器姿勢會向前預測,以反映框架未來可能會超過 20 毫秒的可能姿勢。 這很適合轉譯保留的物件,但會在我們計算使用者放開擲回的那一刻的軌跡時,將目標設為對象的時間問題。 幸運的是,隨著 11 月更新,當傳送 InteractionSourcePressed 或 InteractionSourceReleased 等 Unity 事件時,狀態會包含按下或放開按鈕時從返回的歷史姿勢數據。 若要在擲回期間取得最精確的控制器轉譯和控制器目標,您必須適當地使用輪詢和事件:
- 針對 轉譯 每個畫面的控制器,您的應用程式應該將控制器的 GameObject 放在目前畫面光時間的向前預測控制器姿勢。 您可以從 Unity 輪詢 API 取得此數據,例如 XR。InputTracking.GetLocalPosition 或 XR。WSA。Input.InteractionManager.GetCurrentReading。
- 針對 以 新聞或發行為目標的控制器,您的應用程式應該根據該新聞或發行事件的歷史控制器姿勢來光線廣播和計算軌跡。 您可以從 Unity 事件 API 取得此數據,例如 InteractionManager.InteractionSourcePressed。
使用夾住姿勢。 角度速度和速度是相對於夾住姿勢的回報,而不是指標姿勢。
擲回會隨著未來的 Windows 更新而繼續改善,您可以在這裡找到更多資訊。
MRTK 中的手勢和動作控制器
您可以從輸入管理員存取手勢和動作控制器。
遵循教學課程
混合實境學院提供更詳細的自定義範例逐步教學課程:
下一個開發檢查點
如果您遵循我們制定的 Unity 開發旅程,您正在探索 MRTK 核心建置組塊。 接下來,您可以繼續進行下一個建置組塊:
或者,直接跳到混合實境平台功能和 API 的主題:
您可以隨時回到 Unity 開發檢查點。