さわぐちFMオキーステーション

幸せの鐘が鳴り響き僕はただ嬉しいふりをする

Oculus Questのハンドトラッキングでピンチ判定を行う

f:id:amidaMangrove:20191230171620p:plain

この形を自作アプリ内で取得する方法。

ピンチ判定の方法

OVRHandに以下のメソッドが定義されているのでそれを使用する

メソッド名 戻り値
GetFingerIsPinching 指がピンチ状態かをTrue / Falseで取得
GetFingerPinchStrength ピンチ強度を0~1fで取得
GetFingerConfidence 指のポーズの信頼度をLow / Highで取得

引数にはそれぞれHandFinger型を指定する。

HandFinger.Thumb 親指
HandFinger.Index 人差し指
HandFinger.Middle 中指
HandFinger.Ring 薬指
HandFinger.Pinky 小指

因みに公式のサンプルではこんな感じで使用例がかかれていた

var hand = GetComponent<OVRHand>();
bool isIndexFingerPinching = hand.GetFingerIsPinching(HandFinger.Index);
float ringFingerPinchStrength = hand.GetFingerPinchStrength(HandFinger.Ring);

画面上でピンチ判定を視覚化したいので以下のようなスクリプトを作成し親指~小指までの値を表示してみる。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class HandInfo : MonoBehaviour
{
    [SerializeField]OVRHand _hand;
    Text _info;

    // Start is called before the first frame update
    void Start()
    {
        _info = GetComponent<Text>();
    }

    // Update is called once per frame
    void Update()
    {
        _info.text = "";
        _info.text += $"IsTracked : {_hand.IsTracked}\n";
        _info.text += $"HandConfidence : {_hand.HandConfidence}\n\n";

        _info.text += $"ThumbFingerPinch : {_hand.GetFingerIsPinching(OVRHand.HandFinger.Thumb)}\n";
        _info.text += $"ThumbFingerPinchStrength : {_hand.GetFingerPinchStrength(OVRHand.HandFinger.Thumb)}\n";

        _info.text += $"IndexFingerPinch : {_hand.GetFingerIsPinching(OVRHand.HandFinger.Index)}\n";
        _info.text += $"IndexFingerPinchStrength : {_hand.GetFingerPinchStrength(OVRHand.HandFinger.Index)}\n";

        _info.text += $"MiddleFingerPinch : {_hand.GetFingerIsPinching(OVRHand.HandFinger.Middle)}\n";
        _info.text += $"MiddleFingerPinchStrength : {_hand.GetFingerPinchStrength(OVRHand.HandFinger.Middle)}\n";

        _info.text += $"RingFingerPinch : {_hand.GetFingerIsPinching(OVRHand.HandFinger.Ring)}\n";
        _info.text += $"RingFingerPinchStrength : {_hand.GetFingerPinchStrength(OVRHand.HandFinger.Ring)}\n";

        _info.text += $"PinkyFingerPinch : {_hand.GetFingerIsPinching(OVRHand.HandFinger.Pinky)}\n";
        _info.text += $"PinkyFingerPinchStrength : {_hand.GetFingerPinchStrength(OVRHand.HandFinger.Pinky)}\n";
       
    }
}

f:id:amidaMangrove:20191230173828j:plain

使ってみた個人的な所感だと「親指 + 人差し指」は無理なく判定できるけど、他の指だと結構意識してやらないと微妙な感じ...。ちょっとお遊びでGetFingerPinchStrengthから取得できる値をCubeの拡大率に反映してみた。動作しているコードは以下。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class HandInfo : MonoBehaviour
{
    [SerializeField]OVRHand _hand;
    [SerializeField] GameObject _cube;
    Text _info;
    Vector3 _orignscale;

    // Start is called before the first frame update
    void Start()
    {
        _info = GetComponent<Text>();
        _orignscale = _cube.transform.localScale;
    }

    // Update is called once per frame
    void Update()
    {
        _info.text = "";
        _info.text += $"IsTracked : {_hand.IsTracked}\n";
        _info.text += $"HandConfidence : {_hand.HandConfidence}\n\n";

        _info.text += $"IndexFingerPinch : {_hand.GetFingerIsPinching(OVRHand.HandFinger.Index)}\n";
        _info.text += $"IndexFingerPinchStrength : {_hand.GetFingerPinchStrength(OVRHand.HandFinger.Index)}\n";

        var scale = Mathf.Abs(_hand.GetFingerPinchStrength(OVRHand.HandFinger.Index) - 1);
        _cube.transform.localScale = _orignscale * scale;
        
    }
}

f:id:amidaMangrove:20191231100835g:plain

なるほど。なんか面白い事できそうな気がするかも??