Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
41
Help us understand the problem. What is going on with this article?
@nkjzm

【Oculus Quest】OVRGrabbableでかっこよく銃を実装する

More than 1 year has passed since last update.

はじめに

以下の記事の中で、「Individualなキーマッピングは左右を区別しないため、モノ自体にトリガーを持たせる場合に活躍をする」という話をしました。この記事では、その思想に則ってキー入力を必要とする「銃」の実装を紹介したいと思います。

Oculus Questコントローラーが持つ複数のキーマッピングについて - Qiita
https://qiita.com/nkjzm/items/96cd9cddc645c45dd5e5

環境

  • Unity 2018.3.14f1
  • Oculus Integration for Unity - 1.37
    • Oculus Utilities Plugin 1.32.0
  • Mac OSX 10.14.4(18E226)

適切な位置で銃を掴む

Oculus Integrationを使ってモノを掴むには、主にOVRGrabberOVRGrabbableという2つのクラスを使います。

基本的な使い方については以下の記事が参考になりました。
【Oculus Quest開発メモ】物を掴む、物を投げる OVR Grabber & Grabbable編【Unity】 - Raspberlyのブログ

ここではSnap機能を使い、銃を「適切な位置で掴む」方法を紹介します。

output2.gif

上記のgifを見ると、手に対して銃が適切な位置で固定されていることが分かると思います。

スクリーンショット 2019-06-23 21.03.53.png

設定はOVRGrabbableSnap Position, Snap Orientationにチェックを入れることで可能です。注意したいのがSnap Offsetで、結論から言うとこの項目は使用しない方が良いです(nullでも機能するので)。

手の中心から掴みたいモノの座標をOffset分だけずらすというもので、Snap Offsetで指定したオブジェクトのPositionとRotationが適用されます。ただし、その値はWorld座標系での原点との距離=offsetになるため、非常に使いづらいです。掴みたいモノの子オブジェクトにしてしまうと、手を動かすたびにOffsetの値も変化してしまう挙動をします。

ベストプラクティスとしては、Snap Offsetnullにしておき、掴みたいモノのPrefab側で座標を調整してあげると良いです。掴みたい位置が、そのPrafabの原点になるようRendererの位置をずらすということです。

スクリーンショット 2019-06-23 11.34.56.png

Quest実機で調整してみたところ、掴んだ時の手の原点は中指の付け根あたりにくるようでした。上記画像で矢印が出ているところがPrefabの原点になっているのですが、このように中指の付け根に当たる場所に描画オブジェクトを調整してみてください。Sceneビューでギズモを平行投影に切り替えて2視点から調整すると確実です。

キー取得部分の実装

銃を適切な位置でつかめるようになったので、次はトリガー押下を検知する方法を考えます。

以下はOVRGrabbableを継承したGunクラスです。

Gun.cs
public class Gun : OVRGrabbable, IGrabbable
{
    OVRInput.Controller currentController;
    public void GrabBegin(OVRInput.Controller controller)
    {
        currentController = controller;
    }
   void Update()
    {
        if (isGrabbed && 
        OVRInput.GetDown(OVRInput.Button.PrimaryIndexTrigger, currentController))
        {
            // implement
        }
    }
}

Update()の中身に注目すると、OVRInput.GetDown(OVRInput.Button.PrimaryIndexTrigger, currentController)という記述があります。第二引数に渡しているcurrentControllerは変数になっていて、現在自身を掴んでいる方のコントローラーの値が格納されています。これにより、「モノ自体にトリガーを持たせる」銃が実現できます。

では、掴んでいるコントローラーの値を通知するvoid GrabBegin(OVRInput.Controller controller)の呼び出しについて見てみましょう。IGrabbableというインターフェースで定義されているメソッドになります。

IGrabbable.cs
public interface IGrabbable
{
    void GrabBegin(OVRInput.Controller controller);
}

このメソッドを、掴む側のOVRGrabberを継承したCustomOVRGrabbableから呼び出しています。掴んだオブジェクトがIGrabbableを継承していれば、GrabBegin()を呼び出すという実装です。

CustomOVRGrabbable.cs
using UnityEngine;

public class CustomOVRGrabbable : OVRGrabber
{
    protected override void GrabBegin()
    {
        base.GrabBegin();
        if (m_grabbedObj is IGrabbable)
        {
            ((IGrabbable)m_grabbedObj).GrabBegin(m_controller);
        }
    }
}

これらの実装により、掴む側でなく、掴まれるモノ側にキー入力の定義がある状態を実現出来ました。「指を引いた時、持っているものが銃であったら弾が出る」よりも、今回の実装のように「銃を持っている時、指を引くと弾が出る」の方が、直感的で分かりやすい実装だと思います。

最後に

OVRInputにはキー入力をの他にHapticsの実装なども用意されています。同様にコントローラーを引数に渡せる実装になっているため、今回紹介した方法を同じように適用出来ると思います。

よかったら是非参考にしてみてください。

41
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
nkjzm
特に明示されていない場合、記事中のソースコードはパブリックドメインです。 月額制のメンターサービスで初心者向けの開発サポートをしているので、分からないことがあれば是非こちらで質問してください! → https://menta.work/plan/1115
unity-game-dev-guild
趣味・仕事問わずUnityでゲームを作っている開発者のみで構成されるオンラインコミュニティです。Unityでゲームを開発・運用するにあたって必要なあらゆる知見を共有することを目的とします。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
41
Help us understand the problem. What is going on with this article?