Oculus Quest / Unity もろもろ

Oculus Quest のゲームレビューと、Unityを使った開発について書く

UnityでOculus Questのコントローラに追従して、オブジェクトを打てるオブジェクトを作る

3DのPONGを作ろうとしてハマった。
コントローラに追従するオブジェクトを作るところまでは超簡単なんだけど、そのオブジェクトで別のオブジェクトを打とうとすると難しかった。
普通にやるとオブジェクトのvelocityが常に0であるため、速く振っても単に壁にあたったのと同じ反応になってしまう。

結論だけ知りたい人はラケットにプログラミング

前準備

oculus.hatenablog.com この記事の通りOculus Questの開発準備は整えておく。

コントローラに追従するオブジェクトを作る

これは超簡単。

OVRCameraRigの設置

まずはOVRCameraRigをシーンにドラッグアンドドロップする。
OVRCameraRigは、Oculus開発用のカメラで、専用の機能が色々とついているっぽい。
専用のカメラを置いたので、最初から置いてあるMain Cameraは削除しておく。 f:id:malt03:20190528232555p:plain

オブジェクトを配置

OVRCameraRigを開くと、色々なアンカーがあることがわかる。
そのうちLeftHandAnchor/LeftControllerAnchorRightHandAnchor/RightControllerAnchorがコントローラに追従するアンカー。*1

せっかくなので、Oculus Questのコントローラのモデルを置いてみて実行する。

f:id:malt03:20190528234757p:plain

f:id:malt03:20190528234637j:plain

やったぜ!

オブジェクトを打てるオブジェクトを作る

なかなか難しい

オブジェクトの配置

ラケット

さっきのコントローラのモデルは削除して、Cubeを置く。

ボール

打つためのボールを置く。

Rigidbodyを追加

物理法則に従うオブジェクトにはRigidbodyを設定する必要がある。
ボールとラケットに、メニューの [Component] > [Physics] > [Rigidbody] で追加。
今回は重力を効かせたくないのでRigidbodyUse Gravityはオフにしておく。

このまま実行しても押せるだけで打つことは出来ないし、どんどんラケット位置がズレちゃう。

f:id:malt03:20190529000705p:plain

ラケットにプログラミング

仕方ないのでラケット用にプログラミングしていく。
要するに、オブジェクトの位置がズレないようにしつつ、コントローラが動いた速度でvelocityを無理やり設定してあげれば良い。
以下のコードをRightControllerAnchorコンポーネントとして追加し、racket変数にラケットオブジェクトを設定する。

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

public class Racket : MonoBehaviour
{
    public GameObject racket;
    private Vector3 lastPosition;

    void Start()
    {
        lastPosition = transform.position;
    }

    // Update is called once per frame
    void Update()
    {
        racket.transform.localPosition = Vector3.zero;
        racket.transform.localRotation = Quaternion.identity;
        racket.GetComponent<Rigidbody>().velocity = (transform.position - lastPosition) / Time.deltaTime;
        lastPosition = transform.position;
    }
}

f:id:malt03:20190530011421p:plain

やった!

速いボールを打つ

これで止まっているボールは打てるが、速く向かってきているボールは打てない。
そのあたりは以下の記事にまとめた。

oculus.hatenablog.com

*1:HandAnchor直下にオブジェクト置いても普通に動いたんだけど、ControllerAnchorに置くのとの違いはなんなのか、分かる人は教えて下さい。