Unity3d FingerGestures

目錄



fingerGestures包結構

路徑,相對Assets/Plugin/… 描述
FingerGestures/ 插件的根目錄
FingerGestures/Prefabs 可以直接拖放到場景中的預設資源(prefabs)
FingerGestures/Scripts 核心腳本和組件
FingerGestures/Scripts/Gesture Recognizers 每個手勢識別 的腳本
FingerGestures/Scripts/Finger Event Detectors 每個觸摸事件檢測器的腳本
FingerGestures/Scripts/Components 手勢識別和觸摸事件所需要添加的額外組件
FingerGestures/Toolbox FingerGestures 自帶的工具箱腳本
FingerGestures/Samples.unitypackage 所有例子的子包
FingerGestures/PlayMaker Actions.unitypackage FingerGestures對PlayMaker擴展的插件
Editor/FingerGestures FingerGestures對編輯器的擴展

FingerGestures例子列表

  • Finger Event(鼠標或手指事件) 
    FingerEventsPart1:
     展示如何通過不同的檢測器( FingerEventDetectors )去檢測鼠標或者手指的上(down)、下(up),按下不移動(stationary,懸停(hover) 事件。
    FingerEventsPart2: 展示如何識別不同鼠標或者手指動作(FingerMotionDetector)。

  • Gestures(手勢) 
    BasicGestures:
     識別單擊(react to tap),雙擊(double tap),拖動(drag),長按(long——press),滑動(swipe)等基礎手勢。
    PinchAndTwist: 兩個或多個手指同時在觸摸屏上擠壓(pinch)或扭轉(twist)時,觸發手勢的事件。(PS:通常都是用來縮放或旋轉)
    PointCloudGestures: 示範如何識別一個點雲(point cloud)手勢。(PS:通常是指用用戶畫的圖案作爲識別)

  • Toolbox(工具箱)
    Camera(放入攝像機的腳本):

    Toolbox-DragView: 展示使用TBDragView腳本,實現拖動視角。
    Toolbox-Orbit: 展示使用TBOrbit腳本,實現圍繞目標旋轉視角。
    Toolbox-Pan: 展示使用TBPan腳本,實現以自身爲軸旋轉視角。
    Toolbox-PinchZoom: 展示使用TBPinchZoom腳本,實現變焦。

    Object-Based(放入普通場景對象的腳本):
    Toolbox-Drag: 展示使用TBDrag腳本,實現簡單的物體拖動
    Toolbox-Hover: 展示使用TBHoverChangeMaterial 和 TBHoverChangeScale腳本,實現當鼠標或者手指懸停在物體上時候的響應。(PS:類似鼠標放到圖標上,圖標發亮的效果) 
    Toolbox-PinchToScale 展示使用TBPinchToScale腳本,實現縮放物體
    Toolbox-TwistToRotate: 展示使用TBTwistToRotate腳本,實現旋轉物體

設置場景

需要在場景中實例化一個FingerGesture組件纔可使用。 FingerGesture在項目中的作用是管理用戶輸入和識別手勢和鼠標或手指事件。 
有兩種添加方式,一是直接把Plugins\FingerGestures\Prefabs下的FingerGestures prefab文件拖入場景中。二是可以創建一個空物件,然後把FingerGestures組件添加進去。

1

使用Make Persistent標誌可以讓使FingerGestures 單例在跨場景後一直有效,所以只要保證它在第一個場景設置就足夠。

教程:識別一個輕敲手勢

該章節會學習到如何識別一個簡單的單擊動作,然後到特殊物件的單擊動作識別,最後到識別一個三個手指的雙擊動作。

  • 初始化
    第一步,如上章節設置;
    第二步,創建一個GameObject 命名爲Gestures ;
    第三步,給Gestures添加一個TapRecognizer組件,並保持默認設置,你可以在項目面板搜索到它或者直接打開Component > FingerGestures > Gestures > Tap menu item。

    1

    TapRecognizer 是其中一種手勢識別器,它用於監控用戶輸入而且當一個有效的單擊動作被識別時候工作。
    第四步,創建一個新的C# script 叫做 TapTutorial並添加到第二步創建的Gestures中。

  • 輕敲屏幕
    第一步,點擊TapGestures組件上的Copy Event To Clipboard按鈕,它會把TapGesture所需要的時間信號代碼copy到黏貼板。
    第二步,粘貼到TapTutorial腳本里,如下:

      public class TapTutorial : MonoBehaviour
        {
        void OnTap( TapGesture gesture )
        {
        /* your code here */
        }
        }
        

    OnTap函數匹配定義在TapRecognizer 組件內的信息名屬性,當識別器要識別一個輕敲手勢,它會使用unity3d的SendMessage API先向Gestures物件內所有的腳本廣播OnTap信息,只要TapTutorial綁定在該物件上,它的OnTap函數就會被調用到。
    出於性能考慮,通常使用.net標準的事件模型代替unity3d的SendMessage API。
    第三步,修改OnTop函數:

      void OnTap( TapGesture gesture )
        {
        Debug.Log( "Tap gesture detected at " + gesture.Position +
        ". It was sent by " + gesture.Recognizer.name );
        }
        

    gesture參數包含着手勢事件數據,在上面的代碼,我們主要輸出了位置和TapRecognizer內工作的事件。你還可以在gesture參數內獲得更多屬性,例如通過gesture.Fingers獲得鼠標或手指相關的手勢列表,還有可以通過gesture.Selection獲得當前是哪個場景被輕敲 。
    第四步,可以測試,通過敲不同位置,可以看到debug信息輸出。

教程:手勢識別器

在FingerGesture裏,用戶的手勢都由GestureRecognizers組件來處理,它是順序處理被識別匹配的用戶動作的。

  • 找到GestureRecognizers 
    每種手勢都有自己的腳本,存放腳本的路徑在Plugins\FingerGestures\Scripts\Gesture Recognizers 。1 
    你也可以從 Component > FingerGestures > Gestures menu裏面找到。 
    1

  • 基本使用 
    要識別一個特殊手勢,你需要:
    1、添加對應的GestureRecognizer組件到場景中的目標物件。 
    2、配置它的屬性。 
    3、監聽它的手勢事件和對應響應。

    作爲手勢事件通知的一部分,GestureRecognizer傳遞一個包含相關信息(位置,手指觸屏點列表,選擇的場景物件,相關的GestureRecognizer等)的事件參數。

    一個手勢識別器有以下監聽事件的方式: 
    1、使用標準的.net 委託事件模型,每一個手勢識別器都暴露一個.net事件接口。 
    2、使用unity的SendMessage()函數 :

      手勢事件將會被廣播到遊戲對象裏所有的組件。
        手勢事件也可以指向當前相關的場景對象,這時候需要把手勢識別器配置到 `Raycaster `組件中才能檢測場景對象。
        

    這取決於你的選擇。.net的事件模型較爲高效,unity的SendMessage()較爲方便。

  • 屬性 
    由同一基類派生出來的各種手勢識別器共用一個通用配置和一些函數。例如,我們可以看到TapRecognizerSwipeRecognizer組件的配置放置在同一個對象裏。
    1 
    設置: 
    你可以看到,兩個組件共用了一部分配置:fingers setup,reset mode,event notification settings,references to additional components... 
    同樣,每個手勢識別器都有自己獨特的配置,例如滑動識別器要設置距離閥值、速度、和偏差。而多點觸控可以設置最大持續時間等。

    事件信息廣播: 
    此處使用SendMessage()函數去通知其他系統。你可以使用Message Name屬性去指定響應的函數名。 
    通常,Message Target會設置你加入的手勢識別器組件。但你也可以設置別的對象。

    組件: 
    你可以收到手動指定添加組件。例如:添加一個ScreenRaycaster組件讓手勢識別器獲知場景內對象碰撞。並把消息發送到相應的監聽器。它允許識別器轉發消息到正在有關聯的場景對象。

教程:輕擊手勢識別器

1

  • 屬性 
    Required Taps :連續輕擊的次數。 
    Max Delay Between Taps :兩次輕擊間最大的時間間隔。(秒) 
    Movement Tolerance:連續輕敲時候,和第一次輕擊的位置相隔的偏差大小。 
    Max Duration:最大可以識別的手指數。

  • 事件

      void OnTap( TapGesture gesture )
        {
        // 輕擊的數量
        int taps = gesture.Taps;
        }
        

教程:拖拽手勢識別器

1

  • 屬性 
    Movement Tolerance:最小的拖動距離才觸發識別器。 
    Apply Same Direction Constraint:只能用於多點拖拽,打開後,如果所有點不是向同一個方向拖拽,識別器將不會識別。

  • 事件

      void OnDrag( DragGesture gesture )
        {
        // 當前識別器階段 (Started/Updated/Ended)
        ContinuousGesturePhase phase = gesture.Phase;
        // 最後一幀的拖拽/移動數據
        Vector2 deltaMove = gesture.DeltaMove;
        //完整的拖拽數據
        Vector2 totalMove = gesture.TotalMove;
        }
        

教程:滑動手勢識別器

1

  • 屬性 
    Min Distance: 必須滑動的最小距離。 
    Max Distance:允許滑動的最大距離。 
    Min Velocity:滑動時候最小速度。
    Max Deviation:允許的最大角度偏差。(度)

  • 事件

      void OnSwipe( SwipeGesture gesture )
        {
        // 完整的滑動數據
        Vector2 move = gesture.Move;
        // 滑動的速度
        float velocity = gesture.Velocity;
        // 大概的滑動方向
        FingerGestures.SwipeDirection direction = gesture.Direction;
        }
        

教程:長按手勢識別器

1

  • 屬性 
    Press Duration:最少長按時間。 
    Move Tolerance:長按過程中允許的最大移動偏差。

  • 事件

      void OnLongPress( LongPressGesture gesture )
        {
        // 長按持續時間
        float elapsed = gesture.ElapsedTime;
        }
        

教程:縮放手勢識別器

1

  • 屬性 
    Minimum DOT :允許的小向量點積。 
    Minimum Distance:兩個手指第一次觸屏時候允許的最短路徑。

  • 事件

      void OnPinch( PinchGesture gesture )
        {
        // 識別器當前狀態(Started/Updated/Ended)
        ContinuousGesturePhase phase = gesture.Phase;
        // 當前兩個手指的距離
        float gap = gesture.Gap;
        // 當前與上一幀的變動值
        float delta = gesture.Delta;
        }
        

教程:旋轉手勢識別器

1

  • 屬性 
    Minimum DOT :允許的小向量點積。 
    Minimum Rotation:必須的最小自旋角度。

  • 事件

      void OnTwist( TwistGesture gesture )
        {
        // 識別器當前狀態 (Started/Updated/Ended)
        ContinuousGesturePhase phase = gesture.Phase;
        // 最近一次角度變化(度)
        float delta = gesture.DeltaRotation;
        // 總的角度變化(度)
        float total = gesture.TotalRotation;
        }
        
  • 桌面仿真 
    在桌面環境,你可以通過left-CTRL鍵加上鼠標轉輪去調節角度。也可以在Mouse Input Provider配置別的按鍵。

教程:自定義手勢識別器

自從FingerGestures 3.0之後,可以通過PointCloudRecognizer識別自定義手勢。利用基於$P recognizer 是手勢匹配算法實現。現在只支持單手指操作的識別,將來會支持多點自定義手勢。 
1 
點雲識別器會對比用戶輸入和已經設置好的手勢模板,然後會返回最近接近的匹配結果,會返回匹配得分和差距值。 
點雲識別器是規模和方向固定不變的,這就意味着它可以識別畫得比較大或者小的,也或者是反方向的(李若:從左到右變成從右到左)。

  • 點雲識別器模板 
    一個模板包括要識別的手勢的數據。是通過一個編輯器編輯的。 
    1 
    創建一個模板需要以下步驟: 
    1:在你的項目編碼,右擊-> create ->PonitCloud Gesture Template 
    1 
    一個新的模板就好添加到項目裏面,可以自己重命名。 
    2:選擇模板然後在 Inspecrot 面板內點擊 Edit。 
    1 
    3:然後開始畫圖案。 
    1

  • 使用點雲識別器 
    第一步: 
    1:保證場景對象已經設置好了finger gesture的屬性。 
    2:創建一個新的Gestures對象。 
    3:添加一個PointCloudRecognizer組件。 
    1 
    以下屬性需要特別注意。 
    Max Match Distance:控制識別的精確的程度。數值越低,越精確。 
    Sampling Distance: 連貫動作取樣時候,兩點間隔的最小距離。越小越精確,但是取樣會更多。 
    Gesture Templates List:我們指定的模板列表。

    第二步: 
    添加剛剛創建的模板拖放到手勢模板列表中。 
    1

    第三步: 
    1、創建一個c#文件,此處命名爲PointCloudTutorial.cs。 
    2、在PointCloudRecognizer 下面創建一個手勢對象。 
    3、編輯c#文件:

      public class PointCloudTutorial : MonoBehaviour
        {
        void OnCustomGesture( PointCloudGesture gesture )
        {
        Debug.Log( "Recognized custom gesture: " + gesture.RecognizedTemplate.name +
        ", match score: " + gesture.MatchScore +
        ", match distance: " + gesture.MatchDistance );
        }
        }
        

    手勢事件保護下面幾個重要屬性: 
    gesture.RecognizedTemplate: 被認爲是最佳匹配的手勢模板。 
    gesture.MatchScore:一個百分比的值,表示匹配的程度。 
    gesture.MatchDistance:一個測量絕對值,表示匹配程度。 
    你還可以使用其他手勢的屬性。 例如位置和選擇對象等屬性。

  • 用代碼創建模板 
    你可以使用api字自己的編輯器擴展中在運行時候創建手勢模板。

      void Awake()
        {
        PointCloudGestureTemplate triangle = ScriptableObject.CreateInstance<PointCloudGestureTemplate>();
        triangle.name = "Triangle Gesture Template";
        triangle.BeginPoints();
        triangle.AddPoint( 0, 1, 1 );
        triangle.AddPoint( 0, 2, 2 );
        triangle.AddPoint( 0, 3, 1 );
        triangle.AddPoint( 0, 1, 1 );
        triangle.EndPoints();
        PointCloudGestureTemplate square = ScriptableObject.CreateInstance<PointCloudGestureTemplate>();
        square.name = "Square Gesture Template";
        square.BeginPoints();
        square.AddPoint( 0, 2, 1 );
        square.AddPoint( 0, 2, 3 );
        square.AddPoint( 0, 4, 3 );
        square.AddPoint( 0, 4, 1 );
        square.AddPoint( 0, 2, 1 );
        square.EndPoints();
        PointCloudRegognizer recognizer = gameObject.AddComponent<PointCloudRegognizer>();
        recognizer.AddTemplate( triangle );
        recognizer.AddTemplate( square );
        }
        

    第一個參數AddPoint是一個筆畫的順序,該api暫時只支持單線筆畫的手勢。 
    EndPoints()調用時候,手勢模板會被格式化,所有的點都會重新繪製成0到1範圍的數。

教程:識別手指事件

FingerGestures 可以識別向上,向下,懸停,移動,長按等單點輸入手勢。各種FingerEventDetector組件用於識別對應的手指事件,與 GestureRecognizers類似,都是通過廣播信息去觸發。

  • FingerEventDetector 
    所有的手指事件識別器都派生與一個基礎抽象類。通常,每個FingerEventDetector實例監控着所有手指事件信號。也可以配置Finger Index Filter屬性,讓其只跟蹤特定的手指事件。 
    和手勢識別器一樣,手指事件識別器傳遞一個事件數據對象,改該對象派生於FingerEvent類,包含以下屬性:
屬性 類型 描述
Name string 消息的名字
Detector FingerEventDetector 該次事件中的手指事件識別器
Finger FingerGestures.Finger 該次事件中的手指類
Position Vector2 事件所發生的位置
Selection GameObject 被選中游戲對象 (依賴`ScreenRaycaster `組件)
Hit/td> RaycastHit 光線投射碰撞,由`ScreenRaycaster`提供,在正常顯示上非常有用

  • FingerUpDetector

      void OnFingerUp( FingerUpEvent e )
        {
        //手指已經持續的時間
        float elapsedTime = e.TimeHeldDown;
        }
        
  • FingerHoverDetector

      void OnFingerHover( FingerHoverEvent e )
        {
        // 檢查狀態,是進入還是離開.
        if( e.Phase == FingerHoverPhase.Enter )
        {
        Debug.Log( e.Finger + " entered object: " + e.Selection );
        }
        else if( e.Phase == FingerHoverPhase.Exit )
        {
        Debug.Log( e.Finger + " exited object: " + e.Selection );
        }
        }
        
  • FingerMotionDetector 
    該識別器能夠識別兩種事件。 
    1、OnFingerMove :當手指位置距離上一幀位置有發生變化。 
    2、OnFingerStationary :當手指與上一幀位置一樣。

      void OnFingerMove( FingerMotionEvent e )
        {
        float elapsed = e.ElapsedTime;
        if( e.Phase == FingerMotionPhase.Started )
        Debug.Log( e.Finger + " started moving at " + e.Position);
        else if( e.Phase == FingerMotionPhase.Updated )
        Debug.Log( e.Finger + " moving at " + e.Position );
        else if( e.Phase == FingerMotionPhase.Ended )
        Debug.Log( e.Finger + " stopped moving at " + e.Position );
        }
        void OnFingerStationary( FingerMotionEvent e )
        {
        float elapsed = e.ElapsedTime;
        if( e.Phase == FingerMotionPhase.Started )
        Debug.Log( e.Finger + " started stationary state at " + e.Position );
        else if( e.Phase == FingerMotionPhase.Updated )
        Debug.Log( e.Finger + " is still stationary at " + e.Position );
        else if( e.Phase == FingerMotionPhase.Ended )
        Debug.Log( e.Finger + " stopped being stationary at " + e.Position );
        }
        

建議:使用.net代理事件

當使用unity的SendMessage()函數廣播事件消息非常方便,但是效率低而且不夠.NET代理事件靈活。 
Gesture Events 
每個手勢識別器都暴露一個公共的OnGesture.NET事件,可以匹配手勢事件和手指事件。用法跟用SendMessage()一樣。

    [RequireComponent( typeof( TapGesture ) )]
public class TapTutorial : MonoBehaviour
{
void Start()
{
// 在對象裏面尋找輕擊事件識別器
TapRecognizer tap = GetComponent<TapRecognizer>();
// 訂閱它的.NET事件
tap.OnGesture += MyTapEventHandler;
}
void MyTapEventHandler( TapGesture gesture )
{
Debug.Log( "Tap detected at " + gesture.Position );
}
}

有時候你需要停止監聽事件。你可以用以下辦法:

    tap.OnGesture -= MyTapEventHandler;

注意停止監聽事件時候相關對象的生命週期,有可能會導致內存泄露,這是.NET代理事件的陷阱。

另外一種方法是,FingerGestures單例暴露一個全局的OnGestureEvent鉤子,可以監聽到任何手勢事件。

        void Start()
{
FingerGestures.OnGestureEvent += FingerGestures_OnGestureEvent;
}
void FingerGestures_OnGestureEvent( Gesture gesture )
{
Debug.Log( gesture.Recognizer.name + " fired its gesture event" );
if( gesture is TapGesture )
Debug.Log( "Tapped: " + ((TapGesture)gesture).Taps );
}
  • Finger Event 
    跟上面類似用法。

          FingerUpDetector.OnFingerUp( FingerUpEvent e )
        FingerDownDetector.OnFingerDown( FingerDownEvent e )
        FingerHoverDetector.OnFingerHover( FingerHoverEvent e )
        FingerMotionDetector.OnFingerMove( FingerMotionEvent e )
        FingerMotionDetector.OnFingerStationary( FingerMotionEvent e )
        FingerGestures.OnFingerEvent( FingerEvent e )
        

--EOF

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章