MRが楽しい

MRやVRについて学習したことを書き残す

MRTKを用いてHoloLensのダブルタップを検出する

本日は MRTK の技術調査枠です。
MRTKを用いてダブルクリックならぬダブルタップを検出する方法をまとめます。
以下の記事の応用になります。
bluebirdofoz.hatenablog.com

プロジェクトとシーンの準備

以下の記事を元にHoloLens(WindowsMR)プロジェクトを作成します。
bluebirdofoz.hatenablog.com

2019/2/3現在、MRTK 2017 の最新バージョンは 2017.4.3.0 です。
f:id:bluebirdofoz:20190206060830j:plain

タップイベント

ダブルタップを検出するにはタップイベントを利用します。
前回タップの時刻から一定時刻の間に再びタップイベントが発生すればダブルタップとみなします。
更に連続タップの回数に応じて、ダブルタップ・トリプルタップなどを分けて検出してみます。

MRTK の基本設定を行っていれば IInputClickHandler インタフェースの以下の関数を利用してイベントを取得できます。
・OnInputClicked:タップイベント検出

実際にスクリプトを作成してみます。
ダブルタップとトリプルタップを分けて検出するため、Update 関数を利用して最終タップから一定時刻が経過した時点で連続タップを判定します。
・MultiTapEvent.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// IInputClickHandler を利用するため InputModule を追加
using HoloToolkit.Unity.InputModule;

public class MultiTapEvent : MonoBehaviour,
IInputClickHandler // タップ操作検出
{
    /// <summary>
    /// グローバルリスナーの有無
    /// </summary>
    [Tooltip("グローバルリスナーの有無")]
    public bool IsGlobalListener = false;

    /// <summary>
    /// 連続タップ許容時間(秒)
    /// </summary>
    [SerializeField, Tooltip("連続タップ許容時間(秒)")]
    private float MultTapTime = 0.5f;

    /// <summary>
    /// 連続タップカウント
    /// </summary>
    private int p_MultTapCount;

    /// <summary>
    /// 連続タップ計測開始時刻
    /// </summary>
    private float p_MultTapStart;

    /// <summary>
    /// 起動時処理
    /// </summary>
    void Start ()
    {
        if (IsGlobalListener)
        {
            // 全てのジェスチャーイベントをキャッチする
            // 本設定を有効にしてColliderオブジェクトにアタッチした場合
            // オブジェクトへのタップとグローバルのタップが
            // 別々に検出される(2回処理が走る)ので注意
            InputManager.Instance.AddGlobalListener(gameObject);
        }
    }

    /// <summary>
    /// 定期実行
    /// </summary>
    void Update ()
    {
        // 連続タップ判定
        if (p_MultTapCount > 1)
        {
            // タップカウントが 2 以上の時、連続タップの発生チェック
            if ((Time.time - p_MultTapStart) > MultTapTime)
            {
                // 連続タップ許容時間が経過していればカウントに応じて処理を実行
                if (p_MultTapCount == 2)
                {
                    // ダブルタップ処理
                    Debug.Log("DoubleTap");
                    // オブジェクトを2倍の大きさに変更
                    transform.localScale = transform.localScale * 2.0f;
                }
                if (p_MultTapCount == 3)
                {
                    // トリプルタップ処理
                    Debug.Log("TripleTap");
                    // オブジェクトを1/2の大きさに変更
                    transform.localScale = transform.localScale * 0.5f;
                }
                p_MultTapCount = 0;
            }
        }
    }

    /// <summary>
    /// タップ検出
    /// </summary>
    /// <param name="eventData"></param>
    public void OnInputClicked(InputClickedEventData eventData)
    {
        Debug.Log("clicked!");

        // 現在時刻の取得
        float nowTime = Time.time;

        // 連続タップ確認
        float tapTime = nowTime - p_MultTapStart;
        if (tapTime > MultTapTime)
        {
            // 前回タップから連続タップ許容時間を超えていれば初回タップと再判定
            p_MultTapCount = 1;
        }
        else
        {
            // 前回タップから連続タップ許容時間内ならば連続タップと判定
            p_MultTapCount++;
        }
        // 連続タップ計測開始時刻を更新
        p_MultTapStart = nowTime;
    }
}

作成したスクリプトSphere オブジェクトにアタッチします。
f:id:bluebirdofoz:20190206060848j:plain

[再生]ボタンを押してシーンを開始します。
[Game]ビュー上で Sphere オブジェクトに視線を合わせ Shift + 左クリック でタップ操作を試験できます。
前回のタップから0.5秒以内に連続してタップを行うと、ダブルタップまたはトリプルタップが検出されます。
f:id:bluebirdofoz:20190206060902j:plain

Inspector ビューから MultiTapTime 変数を調整すると、連続タップを検出する許容時間を調整できます。
f:id:bluebirdofoz:20190206060919j:plain