LoginSignup
1
0

[MR Dev Tips #14] UnityEngine.XR InputDevices を使って HoloLens 2 のタップを検出する

Last updated at Posted at 2023-08-30

今回は UnityEngine.XR の InputDevices クラスを使って、HoloLens 2 の Tap を検出してみたいと思います。

検証環境

  • Unity 2020.3
  • MRTK v2.8.3

UnityEngine.XR InputDevices を使って HoloLens 2 のタップを検出する

InputDevices クラスは、XR入力サブシステム (XR Input Subsystem) 内のデバイスにアクセスするためのインターフェースです。InputDevices クラスでは、以下3つの方法で入力デバイスへアクセスが可能です。

  • デバイス特性 (Characteristics)
  • ロール (Role)
  • XRノード (XRNode)

今回は XRNode を用いた入力デバイスへのアクセスを行います。XRNode を用いた入力デバイスへのアクセスは InputDevices.GetDeviceAtXRNode メソッドを使用します。

public static XR.InputDevice GetDeviceAtXRNode (XR.XRNode node);

XRNode は 列挙型 (enum) で定義されています。

XRNode 説明
CenterEye ユーザーの目の瞳孔の中間地点
GameController コンソールスタイルのゲームコントローラーアプリケーションは複数のゲームコントローラーデバイスを持つことができます。
HardwareTracker ハードウェアトラッキングデバイス。通常、ユーザーや物理的なアイテムに取り付けられます。複数のハードウェアトラッカーノードが可能です。
Head XRシステムによって計算された、ユーザーの頭の中心点
LeftEye ユーザーの左目
LeftHand ユーザーの左手
RightEye ユーザーの右目
RightHand ユーザーの右手
TrackingReference Oculusカメラなどのトラッキング基準点。複数のトラッキング参照ノードが存在できます。
// 右手のインスタンスを取得する場合
InputDevice device = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
// 左手のインスタンスを取得する場合
InputDevice device = InputDevices.GetDeviceAtXRNode(XRNode.LeftHand);

デバイスが取得出来たら、次にデバイスの状態を取得します。デバイスの状態を取得する際は、InputDevice.TryGetFeatureValue メソッドを使用します。TryGetFeatureValue() は、機能の現在の値へのアクセスを試行して、以下の結果を返却します。

  • 引数で指定された機能の値を正常に取得した場合は true
  • 現在のデバイスが指定された機能をサポートしていない場合、または、デバイスが無効な場合は false

また、デバイスの機能の指定は、CommonUsage クラスを用いて行います。調査をしていると、HoloLens 2 の タップ は CommonUsage.primaryButton にマッピングされているみたいです。タップ状態の有無は isTapping 変数に格納します。isTappingtrue の場合はタップしている状態、false の場合はタップしていない状態を表します。

device.TryGetFeatureValue(CommonUsages.primaryButton, out bool isTapping);

これらを組み合わせて、(ショート)タップを検出するコードを作成することができます。

Sample.cs
using UnityEngine;
using UnityEngine.XR;

public class Sample : MonoBehaviour
{
  /// <summary>
  /// タップ時間を記録するタップタイマー (右手/左手)
  /// </summary>
  private float[] _tappingTimer = { 0, 0 };

  void Update()
  {
    for (int i = 0; i < 2; i++)
    {
      // 右手/左手のデバイスインスタンスを取得する
      InputDevice device = InputDevices.GetDeviceAtXRNode((i == 0) ? XRNode.RightHand : XRNode.LeftHand);
      // PrimaryButton の現在の状況を取得して、tapping に格納する
      if (device.TryGetFeatureValue(CommonUsages.primaryButton, out bool isTapping))
      {
        // タップをしていない場合
        if (!isTapping)
        {
          // タップが1秒以内であるかどうかを判定
          if (0f < _tappingTimer[i] && _tappingTimer[i] < 1f)
          {
            // タップを検出
            if (device.TryGetFeatureValue(CommonUsages.devicePosition, out Vector3 handPosition))
            {
              // タップされた位置をログ出力
              Debug.Log(handPosition);
            }
          }
            // タップタイマーのリセット
            _tappingTimer[i] = 0;
        }
        // タップをしている場合
        else
        {
          // タップタイマーを更新
          _tappingTimer[i] += Time.deltaTime;
        }
      }
    }
  }
}

以下 GitHub に MS 公式のサンプルコードが用意されているので、興味のある方はこちらを試されるのが良いと思います。

Refs

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0