蒼水技術録

蒼水家技術録

蒼水が普段制作とか勉強とかして覚えたことを復習としてまとめてるものです。 それが最適解かどうかはわからないけど、何を目的として始めて、何が必要で、実際何をやって、どうなったか、まで全部過程を残すための技術ブログです。

VR開発編 #3 -ハンドトラッキングのピンチ度合い(入力)を取ってみる-

どうも、蒼水です。
前回の記事の続きになります。
atelier-aomi.hatenablog.com

今回はハンドトラッキングでピンチ度合い、いわゆる指の閉じ具合を取ってみるところまでやってみたのでまとめていきます。

今回の目的

今回はハンドトラッキングをするうえでやはり操作していくうえで入力って必要ですよね。
Oculusホームで使えるハンドトラッキングでも指を閉じて操作すると思います。これを自分で開発するときにどうやるのか、という部分になります。
これをできるようにすることで指のジェスチャーで操作を可能にします。

OVRHandにある使える関数

GetFingerIsPinching(HandFinger finger)

この関数は指定した指が他の指を触れてるかどうかをBoolで返してくれます。
指にはそれぞれの指を指定できます。(Thumb/Index/Middle/Ring/Pinky)

基本的には親指(Thumb)を指定してやれば他の指と触れてるかどうかになるのでこれで良い気がしました。

GetFingerPinchStrength(HandFinger finger)

この関数は指定した指とのピンチ度合いをfloatで返してくれます。
こちらも同様に指の指定ができ、基本的にはThumbでいいかなと思います。

実際に数値を取って表示してみる


こちらは試しに取った値をテキストで表示してみたものです。
指の動きに合わせてそれぞれ数値が取れてるのが分かると思います。
これを使って条件分岐とかに使って処理を追加していけば何かしらできるのかなーと踏んでいました。

処理を追加してみる


これは上記の2つの関数を使って処理を追加して動かしてみたものです。

手を握ることでうちの子を手をつないでフリフリできるシステムを組んでみました。
うちの子はかわいいなぁ(迫真)

手を握るとはいえ、Thumbを指定しているので他の指をの接触が検出できれば手をつなぐことができるようにしてあります。

サンプルコード

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HandGrabber : MonoBehaviour
{
   //手の指定
    public GameObject LeftHand;
    public GameObject RightHand;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {

    }

    private void OnTriggerStay(Collider other) {

        var lefthand = LeftHand.GetComponent<OVRHand>();
        var righthand = RightHand.GetComponent<OVRHand>();

        float LPitchingStrength = lefthand.GetFingerPinchStrength(OVRHand.HandFinger.Thumb);
        float RPitchingStrength = righthand.GetFingerPinchStrength(OVRHand.HandFinger.Thumb);

        //左手操作
        if (LPitchingStrength >= 0.9) {
            this.gameObject.transform.parent = other.gameObject.transform;
        } else {
            this.gameObject.transform.parent = null;
        }

        //右手操作
        if (RPitchingStrength >= 0.9) {
            this.gameObject.transform.parent = other.gameObject.transform;
        } else {
            this.gameObject.transform.parent = null;
        }
    }
}

解説

まず前提としてこのコードではあらかじめキャラの手を動かすためのIKを使っています。
AnimatorのIK Passにチェックを入れ、それ用のスクリプトを用意していますがここでは割愛します。(別記事で書きたい)

コードとしては手がIK targetになるオブジェクトと接触しているときに閉じ具合が0.9以上の時にIK targetを手の子にすることで移動できるようにしています。
0.9以下のとき親子関係を解除してその場に固定できるようになっています。
LeftHand, RightHandはIK targeになるオブジェクトでOVR Hand Prefabを入れています。

今回はGetFingerPinchStrengthを使用していますがGetFingerPinchでも問題ない気はします。
実際最初そちらでやっていましたがほぼ同じ動きをしていました。

まとめ

基本的には「GetFingerPinchStrength()」「GetFingerPinch()」の二つを使っていくことになるのかな?と思います。
ラッキングの精度はかなり良いのですが手が重なったりするとやはり精度が落ちてしまったり、そもそも手が消えてしまうのでガタついてるのが現状ではあります。
もう少しいい感じにしたいところ....今後検証項目。

親子関係の作成とAnimator使ったIKの話を別記事で書こうかなと思います。