トマシープが学ぶ

Unity/VR/AR/デザイン好きのミーハー 記事内容は自分用のメモです

腕を振る移動ジェスチャーで移動したい【Meta】

VRでの移動方法

前回ハンドジェスチャーでテレポート移動はできた。

bibinbaleo.hatenablog.com

でも諸事情でテレポート移動ではなく、アバターが少しずつ動いて移動したい。

傍から見たときに瞬間移動するのではなくちゃんと歩いて移動したように見えたい。

 

腕を振ったら移動するようなのが、コントローラーを使わない中での方法だといいのかなと思った。

vcl.jp

この記事にいろいろな操作方法が書いてある

zenn.dev

 

ハンドジェスチャの認識はIntaractionSDKのサンプル内にもあった。

実際に手話の認識をやっている人もいる

zenn.dev

でも腕を振るというのはハンドジェスチャの認識なのだろうか?

Intarection SDKのサンプルの中にそのポーズをしたかどうか判定してくれるものもあった。これ使えないかな~?ポーズと動作では違うかな。判定も結構シビアだったしな

実装1(ChatGPT)

ChatGPTに聞いたら速度で判定したらといわれた。でもこれだと手を素早く動かしたら移動判定になっちゃうのかな?

とりあえずChatGPTに依頼して作ってもらったコードで動かしたら、手を振ったときに移動するというのはできた。

using UnityEngine;

public class HandMovementController : MonoBehaviour
{
    public Transform leftHandTransform; // 左手のTransformをInspectorから割り当てる
    public Transform rightHandTransform; // 右手のTransformをInspectorから割り当てる
    public Transform hmdTransform; // HMDのTransformをInspectorから割り当てる

    public GameObject cameraRig; // CameraRigオブジェクトをInspectorから割り当てる
    public float movementSpeed = 1.0f; // 移動速度
    public float handMovementThreshold = 0.05f; // 手の動きのしきい値

    private Vector3 previousLeftHandPosition;
    private Vector3 previousRightHandPosition;
    private bool isLeftHandMoving;
    private bool isRightHandMoving;

    void Start()
    {
        // 初期位置を記録
        previousLeftHandPosition = leftHandTransform.position;
        previousRightHandPosition = rightHandTransform.position;
    }

    void Update()
    {
        Vector3 currentLeftHandPosition = leftHandTransform.position;
        Vector3 currentRightHandPosition = rightHandTransform.position;
        Vector3 hmdForward = Quaternion.Euler(0, hmdTransform.eulerAngles.y, 0) * Vector3.forward;

        // 左右の手の前後の動きを判定
        isLeftHandMoving = IsHandMoving(currentLeftHandPosition, previousLeftHandPosition);
        isRightHandMoving = IsHandMoving(currentRightHandPosition, previousRightHandPosition);

        // 交互に手が動いているかを判定
        if (isLeftHandMoving != isRightHandMoving)
        {
            // HMDの向いている方向に水平移動
            cameraRig.transform.position += hmdForward * movementSpeed * Time.deltaTime;
        }

        // 現在の手の位置を更新
        previousLeftHandPosition = currentLeftHandPosition;
        previousRightHandPosition = currentRightHandPosition;
    }

    bool IsHandMoving(Vector3 currentHandPosition, Vector3 previousHandPosition)
    {
        // 手の動きがしきい値より大きいかを判定
        return (currentHandPosition - previousHandPosition).magnitude > handMovementThreshold;
    }
}

動きがかなりかくかくしてる・・・

あと手を振るとかほかの動作をしているときにも動く。

Godotのシーンをもう一度いろいろ動かしたが、片手だけ降っているときとかバイバイ👋の動作とか、両手を同時に同じ方向に振るとかをやっても動かない。

ちゃんと左右交互に走るときみたいに動かしたときだけ反応する。

あとGodotは移動パワーが加わってる感じでスーって動く

もうGodotの実装見ようと思ったが、どこが実装のコードなのかわからない。それっぽいのないんだけど;;

実装2

私のググり方が悪いだけでどこかにコードあるかもと思ってcopilotに聞いたら普通に出てきた。

qiita.com

こちらはOVRPlayerControllerがある状態で動く

ハンドトラッキングだと動かなかったが、コントローラーを持った状態だと動いた。

スクリプト内でコントローラー参照しているな~

ただこちらも同じく手を振る動作とかでも少し移動してしまう。ChatGPTのよりは誤作動少なそうだが

ChatGPTのと違うのは頭の方向じゃなくてコントローラーを振った方向に移動する。前後じゃなくて左右気味に動かしたらそちらに動く。頭を動かさないでいいので便利。

ChatGPTに聞いて

//touchVelocityL
//    = OVRInput.GetLocalControllerVelocity(OVRInput.Controller.LTouch);

の部分を手の位置から計算したVelocityなどに変えてハンドトラッキングモードでも動くようにスクリプト変更しようとしたが、手を動かすと動きはするが移動する向きが合わない・・・

ちなみにOVRInput.GetLocalControllerVelocityで検索したら別の腕振り移動記事が出てきた。

qiita.com

手の加速度

communityforums.atmeta.com