UnityでOculus Questのコントローラに追従して、オブジェクトを打てるオブジェクトを作る
3DのPONGを作ろうとしてハマった。
コントローラに追従するオブジェクトを作るところまでは超簡単なんだけど、そのオブジェクトで別のオブジェクトを打とうとすると難しかった。
普通にやるとオブジェクトのvelocity
が常に0であるため、速く振っても単に壁にあたったのと同じ反応になってしまう。
結論だけ知りたい人はラケットにプログラミングへ
前準備
oculus.hatenablog.com この記事の通りOculus Questの開発準備は整えておく。
コントローラに追従するオブジェクトを作る
これは超簡単。
OVRCameraRigの設置
まずはOVRCameraRig
をシーンにドラッグアンドドロップする。
OVRCameraRig
は、Oculus開発用のカメラで、専用の機能が色々とついているっぽい。
専用のカメラを置いたので、最初から置いてあるMain Camera
は削除しておく。
オブジェクトを配置
OVRCameraRig
を開くと、色々なアンカーがあることがわかる。
そのうちLeftHandAnchor/LeftControllerAnchor
とRightHandAnchor/RightControllerAnchor
がコントローラに追従するアンカー。*1
せっかくなので、Oculus Questのコントローラのモデルを置いてみて実行する。
やったぜ!
オブジェクトを打てるオブジェクトを作る
なかなか難しい
オブジェクトの配置
ラケット
さっきのコントローラのモデルは削除して、Cubeを置く。
ボール
打つためのボールを置く。
Rigidbodyを追加
物理法則に従うオブジェクトにはRigidbodyを設定する必要がある。
ボールとラケットに、メニューの [Component] > [Physics] > [Rigidbody] で追加。
今回は重力を効かせたくないのでRigidbody
のUse Gravity
はオフにしておく。
このまま実行しても押せるだけで打つことは出来ないし、どんどんラケット位置がズレちゃう。
ラケットにプログラミング
仕方ないのでラケット用にプログラミングしていく。
要するに、オブジェクトの位置がズレないようにしつつ、コントローラが動いた速度で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; } }
やった!
速いボールを打つ
これで止まっているボールは打てるが、速く向かってきているボールは打てない。
そのあたりは以下の記事にまとめた。
*1:HandAnchor直下にオブジェクト置いても普通に動いたんだけど、ControllerAnchorに置くのとの違いはなんなのか、分かる人は教えて下さい。