Hololens開發筆記之Gesture手勢識別(手勢檢測反饋)


本文實現當使用者手出現在Hololens視野范圍內時,跟蹤手並給出反饋的效果。

1、在Manager上添加HandsManager腳本組件,用於追蹤識別手

 

HandsManager.cs如下(直接使用HoloTooKit中腳本)

// Copyright (c) Microsoft Corporation. All rights reserved.  
// Licensed under the MIT License. See LICENSE in the project root for license information.  
  
using System.Collections.Generic;  
using UnityEngine.VR.WSA.Input;  
  
namespace HoloToolkit.Unity  
{  
    /// <summary>  
    /// HandsManager determines if the hand is currently detected or not.  
    /// </summary>  
    public partial class HandsManager : Singleton<HandsManager>  
    {  
        /// <summary>  
        /// HandDetected tracks the hand detected state.  
        /// Returns true if the list of tracked hands is not empty.  
        /// </summary>  
        public bool HandDetected  
        {  
            get { return trackedHands.Count > 0; }  
        }  
  
        private HashSet<uint> trackedHands = new HashSet<uint>();  
  
        void Awake()  
        {  
            //識別到來源  
            InteractionManager.SourceDetected += InteractionManager_SourceDetected;  
            //來源丟失  
            InteractionManager.SourceLost += InteractionManager_SourceLost;  
        }  
  
        private void InteractionManager_SourceDetected(InteractionSourceState state)  
        {  
            // 檢測來源是否為手,如果是手則加入跟蹤集合  
            if (state.source.kind != InteractionSourceKind.Hand)  
            {  
                return;  
            }  
  
            trackedHands.Add(state.source.id);  
        }  
  
        private void InteractionManager_SourceLost(InteractionSourceState state)  
        {  
            // 檢測丟失的來源是否為手,如果是手則從跟蹤集合中去除  
            if (state.source.kind != InteractionSourceKind.Hand)  
            {  
                return;  
            }  
  
            if (trackedHands.Contains(state.source.id))  
            {  
                trackedHands.Remove(state.source.id);  
            }  
        }  
  
        void OnDestroy()  
        {  
            InteractionManager.SourceDetected -= InteractionManager_SourceDetected;  
            InteractionManager.SourceLost -= InteractionManager_SourceLost;  
        }  
    }  
}  

該腳本中使用到了底層API   Interaction Input

底層API運行獲得輸入來源的更多詳細信息,例如它在世界中的位置和速度。

如何處理底層交互事件
使用底層交互是很容易的:
1) 注冊InteractionManager事件
2) 處理事件
停止它也很容易:
1) 取消注冊事件

處理底層交互事件
一旦注冊了底層交互事件,在事件發生時你就可以得到回調。你可以使用獲取到的時間信息來處理應用行為。

void InteractionManager_SourcePressed(InteractionSourceState state)  
{  
// state變量里包含以下信息:  
// 當前凝視射線信息  
// 來源是否被點擊  
// 位置、速度之類的屬性  
// 來源id和來源類型 ( hand, voice, controller或其他)  
}  

如何停止交互事件
當你不再想要關注一些事件后,只需要取消時間注冊即可。

InteractionManager.SourcePressed -= InteractionManager_SourcePressed;  

輸入源變化事件
這些事件描述了輸入源的當前狀態:
1) detected( 即將激活)
2) lost( 即將取消激活)
3) updates( 移動或者一些狀態在變化)
4) is pressed( 點擊、按鈕按下或者語音選中)
5) is released( 點擊結束,按鈕松開,語音選中結束)


輸入源狀態
每個事件都會有一個InteractionSourceState參數,這個參數代表了實時輸入源狀態:
1) 是否是點擊狀態
2) InteractionSourceProperties包含了輸入源位置信息 InteractionSourceLocation,能夠獲得當前輸入源位置和速度信息
3) 凝視射線信息,用於判斷事件發生時用戶是否在注視目標
4) 來源類型信息,包括hand、voice、controller或者其他類型

2、在Cursor下新建Empty對象,並重命名為CursorBillboard,並添加Billboard腳本組件

 

Billboard腳本如下(可以直接在HoloToolKit中找到)

// Copyright (c) Microsoft Corporation. All rights reserved.  
// Licensed under the MIT License. See LICENSE in the project root for license information.  
  
using UnityEngine;  
  
namespace HoloToolkit.Unity  
{  
    public enum PivotAxis  
    {  
        // Rotate about all axes.  
        Free,  
        // Rotate about an individual axis.  
        X,  
        Y  
    }  
  
    /// <summary>  
    /// The Billboard class implements the behaviors needed to keep a GameObject  
    /// oriented towards the user.  
    /// </summary>  
    public class Billboard : MonoBehaviour  
    {  
        /// <summary>  
        /// The axis about which the object will rotate.  
        /// </summary>  
        [Tooltip("Specifies the axis about which the object will rotate (Free rotates about both X and Y).")]  
        public PivotAxis PivotAxis = PivotAxis.Free;  
  
        /// <summary>  
        /// Overrides the cached value of the GameObject's default rotation.  
        /// </summary>  
        public Quaternion DefaultRotation { get; private set; }  
  
        private void Awake()  
        {  
            // Cache the GameObject's default rotation.  
            DefaultRotation = gameObject.transform.rotation;  
        }  
  
        /// <summary>  
        /// Keeps the object facing the camera.  
        /// </summary>  
        private void Update()  
        {  
            // Get a Vector that points from the Camera to the target.  
            Vector3 forward;  
            Vector3 up;  
  
            // Adjust for the pivot axis. We need a forward and an up for use with Quaternion.LookRotation  
            switch (PivotAxis)  
            {  
                // If we're fixing one axis, then we're projecting the camera's forward vector onto  
                // the plane defined by the fixed axis and using that as the new forward.  
                case PivotAxis.X:  
                    Vector3 right = transform.right; // Fixed right  
                    forward = Vector3.ProjectOnPlane(Camera.main.transform.forward, right).normalized;  
                    up = Vector3.Cross(forward, right); // Compute the up vector  
                    break;  
  
                case PivotAxis.Y:  
                    up = transform.up; // Fixed up  
                    forward = Vector3.ProjectOnPlane(Camera.main.transform.forward, up).normalized;  
                    break;  
  
                // If the axes are free then we're simply aligning the forward and up vectors  
                // of the object with those of the camera.   
                case PivotAxis.Free:  
                default:  
                    forward = Camera.main.transform.forward;  
                    up = Camera.main.transform.up;  
                    break;  
            }  
  
  
            // Calculate and apply the rotation required to reorient the object  
            transform.rotation = Quaternion.LookRotation(forward, up);  
        }  
    }  
}  

3、在Cursor上添加CursorFeedback腳本組件

1) 在HoloToolkit -> Input -> Prefabs中找到HandDetectedFeedback Prefab 並拖到CursorFeedback的hand detected asset上

2) 將剛才創建的CursorBillboard拖到CursorFeedback的Feedback Parent上

CursorFeedback腳本如下((可以直接在HoloToolKit中找到))

// Copyright (c) Microsoft Corporation. All rights reserved.  
// Licensed under the MIT License. See LICENSE in the project root for license information.  
  
using UnityEngine;  
  
namespace HoloToolkit.Unity  
{  
    /// <summary>  
    /// CursorFeedback class takes GameObjects to give cursor feedback  
    /// to users based on different states.  
    /// </summary>  
    public class CursorFeedback : MonoBehaviour  
    {  
        [Tooltip("Drag a prefab object to display when a hand is detected.")]  
        public GameObject HandDetectedAsset;  
        private GameObject handDetectedGameObject;  
  
        [Tooltip("Drag a prefab object to parent the feedback assets.")]  
        public GameObject FeedbackParent;  
  
        void Awake()  
        {  
            if (HandDetectedAsset != null)  
            {  
                handDetectedGameObject = InstantiatePrefab(HandDetectedAsset);  
            }  
            else  
            {  
                Debug.LogError("Missing a required game object asset.  Check HandDetectedAsset is not null in editor.");  
            }  
        }  
  
        private GameObject InstantiatePrefab(GameObject inputPrefab)  
        {  
            GameObject instantiatedPrefab = null;  
  
            if (inputPrefab != null && FeedbackParent != null)  
            {  
                instantiatedPrefab = GameObject.Instantiate(inputPrefab);  
                // Assign parent to be the FeedbackParent  
                // so that feedback assets move and rotate with this parent.  
                instantiatedPrefab.transform.parent = FeedbackParent.transform;  
  
                // Set starting state of the prefab's GameObject to be inactive.  
                instantiatedPrefab.gameObject.SetActive(false);  
            }  
            else  
            {  
                Debug.LogError("Missing a required game object asset.  Check FeedbackParent is not null in editor.");  
            }  
  
            return instantiatedPrefab;  
        }  
  
        void Update()  
        {  
            UpdateHandDetectedState();  
        }  
  
        private void UpdateHandDetectedState()  
        {  
            if (handDetectedGameObject == null)  
            {  
                return;  
            }  
  
            handDetectedGameObject.SetActive(HandsManager.Instance.HandDetected);  
        }  
    }  
}  

4、運行測試

 

當手出現在Hololens視野中時,手被檢測到,在凝視射線處出現一個藍色的小手(Hololens模擬器中需要處於hold狀態才會出現藍色小手,真機上只要手舉起就可以)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM