BlenderとUnityで作ったものをVR(Oculus  Quest/Oculus Link)で動かします

VRで焚き火する #10 薪オブジェクトを直接つかむ【Unity】

 
前回の記事では、キャンプ場を暗くして夜に焚き火をしてみました。
 
これまでは薪オブジェクトに火をつけただけでしたので、今回はVRモードで薪をつかめるようプログラムしてみます。
やっと焚き火っぽくなってきましたよ。



開発環境

・Unity 2020.3.10f1(High Definition RP 10.5.0)
・グラボ:ASUS ROG-STRIX-RTX2060S-O8G-GAMING
・Oculus Quest 2(Oculus Link利用)
・炎アセット:Ignis – Interactive Fire
 

(1) コントローラで物をつかむ

VRモードで物をつかみたい場合、Oculus標準の OVRGrabber やhecomi様の VR Grabber などを使う方法があります。
以前の記事では、VR Grabber を使わせていただきましたね。
 
それを使っても良いのですが、将来的には掴んだ時の処理を自分でカスタマイズしたいですので、今回は自分でプログラムすることにしました。
 

コントローラの子オブジェクトにすれば掴める

調べてみると、物を掴むだけならそこまで難しくは無いようです。
 
実装には以下のサイトを参考にさせていただきました。
ありがとうございました!
 
ポイントは「コントローラの子オブジェクトにする」ですね。
 

右ハンドトリガーを押している時の処理

OVRCameraRig にアタッチしているスクリプト」の LateUpdateメソッド内に、以下の処理を追加します。
私のUnityプロジェクトの場合、コントローラでの移動用に TransformMover.cs というスクリプトを作っていましたので、ここに追加しました。
 
まずは、トリガーを押した時の実装です。
 
[TransformMover.cs]
// 右ハンドトリガーを押している時
if (OVRInput.Get(OVRInput.Button.SecondaryHandTrigger, OVRInput.Controller.Touch))
{
    RaycastHit[] hits;
    hits = Physics.SphereCastAll(RightHandAnchor.transform.position, 0.01f, Vector3.forward);
    foreach (var hit in hits)
    {
        if (hit.collider.CompareTag("Grab"))
        {
            hit.collider.transform.parent = RightHandAnchor.transform;
            hit.collider.transform.GetComponent<Rigidbody>().useGravity = false;
            hit.collider.transform.GetComponent<Rigidbody>().isKinematic = true;
            break;
        }
    }
}
 
2行目で、右コントローラーの「ハンドトリガー」が押されたことを検知。
4,5行目で、コントローラから出したRay(見えないビームみたいなもの)が他のオブジェクトのコライダーに当たったかを取得。
6~15行目で、当たった中身をチェックしています。同時に複数ヒットする可能性があるので、foreachでループしているようです。
 
なお、薪オブジェクトには事前に「Grab」というタグ名を設定しておきました。
 
Rayが当たったオブジェクトのタグ名が「Grab」の場合、8行目のIf文が true になります。
そして、10行目の処理で「当たったオブジェクト(=薪オブジェクト)」の親を「コントローラ」に設定することで、掴んだ状態になります。こういう方法があったんですね。
 
ちなみに11,12行目では、薪オブジェクトの Rigidbodyコンポーネントの設定を変更してます。
掴んでいる間、重力は関係ありませんので useGravity を false にします。
 
逆に、isKinematic(物理演算の影響の有無)は true ですね。true にすると影響を受けそうですが、実は逆で「影響を受けない」になります。私も最初は反対の意味だと思ってましたよ。
 

右ハンドトリガーを離した時の処理

次に、トリガーを離した時の実装です。
 
基本的には掴んだ時とは逆の処理になります。
 
// 右ハンドトリガーを離した時
if (OVRInput.GetUp(OVRInput.Button.SecondaryHandTrigger, OVRInput.Controller.Touch))
{
    for (int i = 0; i < RightHandAnchor.transform.childCount; i++)
    {
        var child = RightHandAnchor.transform.GetChild(i);
        if (child.CompareTag("Grab"))
        {
            child.parent = null;
            child.GetComponent<Rigidbody>().useGravity = true;
            child.GetComponent<Rigidbody>().isKinematic = false;
        }
    }
}
 
9行目で、parent に null を代入することで、オブジェクトの親子関係を無くしています。
10,11行目で、重力と物理演算の影響をオンに戻してます。
 
これで完了です。
 


(2) 動画で確認してみる

VRモード(Oculus Link)で操作してみました。
 

オブジェクトを掴んで離す

動画で確認してみます。
 
ちゃんと薪オブジェクトを掴んで離すことができました。
 

まとめ 

コントローラで薪オブジェクトを掴んで離してみました。
 
無事につかめたのは良いのですが、手で直接つかむにはオブジェクトにかなり近づかないといけないので少し面倒です。
もっと遠くからオブジェクトをつかめると便利ですね。
 
次回は、コントローラからビームっぽいものを出して、それでオブジェクトをつかみます。
 
スポンサーリンク

コメント

  • トラックバックは利用できません。

  • コメント (0)

  1. この記事へのコメントはありません。

VRで焚き火する #9 夜に焚き火をしてみる【Unity】

VRで焚き火する #11 コントローラーからレーザーを出して薪をつかむ【Unity】

最近のコメント

だーしゅ
IT関係のお仕事してます。
VRは楽しいですね。

[当ブログについて]