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)

Namespace:UnityEngine.XR.WSA.Input
類型GestureRecognizerGestureSettingsInteractionSourceKind

您的應用程式也可以辨識空間輸入來源、點選、按住、操作和流覽手勢的高階複合手勢。 您可以使用 GestureRecognizer 跨 雙手運動控制器 辨識這些複合手勢。

GestureRecognizer 上的每個 Gesture 事件都會提供輸入的 SourceKind,以及事件時的目標前端光線。 某些事件提供其他內容特定資訊。

使用手勢辨識器擷取手勢只需要幾個步驟:

  1. 建立新的手勢辨識器
  2. 指定要watch的手勢
  3. 訂閱這些手勢的事件
  4. 開始擷取手勢

建立新的手勢辨識器

若要使用 GestureRecognizer,您必須已建立 GestureRecognizer

GestureRecognizer recognizer = new GestureRecognizer();

指定要watch的手勢

透過 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 () 在處理 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 中轉譯動作控制器模型

動作控制器模型和遠端傳送
動作控制器模型和電匯

若要在應用程式中轉譯符合使用者所按住的實體控制器,並在按下各種按鈕時表達動作控制器,您可以在Mixed Reality Toolkit中使用MotionController 預製專案。 這個預製物件會在執行時間從系統的已安裝動作控制器驅動程式動態載入正確的 glTF 模型。 請務必以動態方式載入這些模型,而不是在編輯器中手動匯入這些模型,讓您的應用程式針對使用者可能擁有的任何目前和未來控制器顯示實際精確的 3D 模型。

  1. 請依照消費者入門指示下載 Mixed Reality Toolkit,並將其新增至 Unity 專案。
  2. 如果您將相機取代為MixedRealityCameraParent預製專案做為消費者入門步驟的一部分,您可以繼續! 該預製專案包含動作控制器轉譯。 否則,從 [專案] 窗格將 Assets/HoloToolkit/Input/Prefabs/MotionControllers.prefab 新增至場景。 您會想要將該預製物件新增為您在場景中使用者電報時用來移動相機的任何父物件的子系,讓控制器與使用者一起移動。 如果您的應用程式未涉及遠端傳送,只要在場景的根目錄中新增預製專案即可。

擲回物件

在虛擬實境中擲回物件是比一開始可能更困難的問題。 如同大部分以實際為基礎的互動,在遊戲中擲回時會以非預期的方式運作時,它會立即明顯並中斷沈浸式。 我們已花一些時間深入思考如何代表實際正確的擲回行為,並透過我們平臺的更新啟用一些指導方針,讓我們想要與您分享。

您可以在這裡找到如何 實作擲回的範例。 此範例遵循下列四個指導方針:

  • 使用控制器 的速度 ,而不是位置。 在 Windows 的 11 月更新中,我們在 「大約」位置追蹤狀態時引進了行為變更。 當處於此狀態時,只要我們認為控制器的高精確度,速度資訊仍會持續回報,這通常比位置長仍高精確度。

  • 併入控制器的角速度。 此邏輯全都包含在 throwing.cs 靜態方法的 GetThrownObjectVelAngVel 檔案中,且在上述連結的套件內:

    1. 當角度速度受到節省時,擲回的物件必須維持與擲回時相同的角度速度: objectAngularVelocity = throwingControllerAngularVelocity;

    2. 由於擲回物件的品質中心可能不在底板姿勢的原點,因此其速度可能會與使用者參考框架中的控制器速度不同。 以這種方式貢獻的物件速度部分是控制器原點周圍所擲回物件之品質中心的即時正切速度。 這個正切速度是控制器角度速度的交叉乘積,其向量代表控制器原點與擲回物件之品質中心之間的距離。

      Vector3 radialVec = thrownObjectCenterOfMass - throwingControllerPos;
      Vector3 tangentialVelocity = Vector3.Cross(throwingControllerAngularVelocity, radialVec);
      
    3. 擲回物件的總速度是控制器的速度和這個正切速度的總和: objectVelocity = throwingControllerVelocity + tangentialVelocity;

  • 請密切注意我們套用速度的時間。 按下按鈕時,最多可能需要 20 毫秒的時間,該事件才能透過藍牙升升至作業系統。 這表示,如果您輪詢控制器狀態的變更,從按下變更為未按下,或以其他方式輪詢,控制器就會呈現您取得的資訊,實際上會超過此變更的狀態。 此外,我們輪詢 API 所呈現的控制器姿勢會向前預測,以反映框架未來可能超過 20 毫秒的可能姿勢。 這很適合 譯保留的物件,但會在使用者放開擲回時計算出動作的路線時,將時間問題複合在 目標 物件上。 幸好,當 傳送 InteractionSourcePressedInteractionSourceReleased 等 Unity 事件時,狀態會包含按下或放開按鈕時的歷史姿勢資料。 若要在擲回期間取得最精確的控制器轉譯和控制器目標,您必須適當地正確使用輪詢和事件:

  • 使用底框姿勢。 Angular速度與速度會相對於底框姿勢來報告,而不是指標姿勢。

擲回將會隨著未來的 Windows 更新繼續改善,您可以在這裡找到詳細資訊。

MRTK 中的手勢和動作控制器

您可以從輸入管理員存取手勢和動作控制器。

遵循教學課程

Mixed Reality Academy 提供更詳細的自訂範例逐步教學課程:

MR 輸入 213 - 動作控制器
MR 輸入 213 - 動作控制器

下一個開發檢查點

如果您遵循我們配置的 Unity 開發旅程,您正在探索 MRTK 核心建置組塊。 接下來,您可以繼續進行下一個建置組塊:

或者,直接跳到混合實境平台功能和 API 的主題:

您可以隨時回到 Unity 開發檢查點

另請參閱