前回の記事でOculus Go向けのビルドはできるようになりました。
今回は前回のプロジェクト(と言ってもCubeやSphereを置いただけですが)にOculus Goコントローラーを追加していきます。
1:必要なアセットのインポート
プロジェクトを開いたらメニューの「Window」→「Asset Store」を選択します。
するとAsset Storeの画面が出てくるので「Oculus Integration」と入力して検索ボタンを押します。
Oculus Integrationのアセットをダウンロードしてない場合はダウンロードします。
ダウンロードが終わったら「Import」ボタンを押してアセットをインポートします。
インポートの途中で以下のダイアログが出てきた場合は「Yes」ボタンを押します。
そのあとUnityを再起動するかを尋ねるダイアログが出てくるので、それもYesボタンをクリックしてUnityを再起動させます。
Unityの再起動が終わって開いていたプロジェクトが再び立ち上がると、Assets配下に「Oculus」というフォルダが追加されています。この中にOculus向けアプリ開発に必要なものが入っています。
これでアセットのインポートは完了です。
2:OVRCameraRigの追加しMain Cameraを削除する
初めにOVRCameraRigというVR用のカメラを追加します。
「Oculus」→「VR」→「Prefabs」の中にある「OVRCameraRig」をドラッグ&ドロップでSceneに追加します。
これで元のカメラがいらなくなるので「Main Camera」を選択した状態で右クリックし、「Delete」を選択して削除します。
3:Oculus Goコントローラーの追加
次はOculus Go用のコントローラーを追加します。
「Oculus」→「VR」→「Prefabs」の中にある「TrackedRemote」を「OVRCameraRig」の中にある「LeftHandAnchor」と「RightHandAnchor」にドラッグ&ドロップします。
「LeftHandAnchor」と「RightHandAnchor」の両方に配置しておくことで、右手・左手の設定から自動的にどちらを表示するかを決めてくれます。
追加した「TrackedRemote」の子として「OculusGoControllerModel」というのがあります。これがOculus Goのコントローラーになります。
単にコントローラーを追加するだけならこれで終わりです。
4:Oculus Goコントローラーからレーザーポインターを出す
追加したコントローラーがどこを指しているかがわかるように、コントローラーの先からレーザーポインターを出すようにします。
最初に「Assets」フォルダを選択した状態で右クリックをし「Create」→「Folder」を選択し、「Scripts」という名前のフォルダを作成します。ここにスクリプトを追加していきます。
次に「Scripts」フォルダを選択した状態で右クリックをし「Create」→「C# Script」を選択し、「LaserPointer」という名前で.csファイルを作成します。
作成した「LaserPointer」ファイルをダブルクリックしてエディタを開き、以下のようにソースコードを記述します。
using System.Collections; using System.Collections.Generic; using UnityEngine; /** * レーザーポインターを出すクラス */ public class LaserPointer : MonoBehaviour { [SerializeField] private Transform _RightHandAnchor; // 右手 [SerializeField] private Transform _LeftHandAnchor; // 左手 [SerializeField] private Transform _CenterEyeAnchor; // 目の中心 [SerializeField] private float _MaxDistance = 100.0f; // 距離 [SerializeField] private LineRenderer _LaserPointerRenderer; // LineRenderer // コントローラー private Transform Pointer { get { // 現在アクティブなコントローラーを取得 var controller = OVRInput.GetActiveController(); if (controller == OVRInput.Controller.RTrackedRemote) { return _RightHandAnchor; } else if (controller == OVRInput.Controller.LTrackedRemote) { return _LeftHandAnchor; } // どちらも取れなければ目の間からビームが出る return _CenterEyeAnchor; } } void Update () { var pointer = Pointer; // コントローラーを取得 // コントローラーがない or LineRendererがなければ何もしない if (pointer == null || _LaserPointerRenderer == null) { return; } // コントローラー位置からRayを飛ばす Ray pointerRay = new Ray(pointer.position, pointer.forward); // レーザーの起点 _LaserPointerRenderer.SetPosition(0, pointerRay.origin); RaycastHit hitInfo; if (Physics.Raycast(pointerRay, out hitInfo, _MaxDistance)) { // Rayがヒットしたらそこまで _LaserPointerRenderer.SetPosition(1, hitInfo.point); } else { // Rayがヒットしなかったら向いている方向にMaxDistance伸ばす _LaserPointerRenderer.SetPosition(1, pointerRay.origin + pointerRay.direction * _MaxDistance); } } }
ソースコードの記述が終わったら、Sceneの何も選択していない状態で右クリックをし「Create Empty」を選択します。
すると空のGame Objectが作成されるので、名前を「LaserPointer」に変更します。
名前を変更した「LaserPointer」のGame ObjectにScriptsフォルダの中にある「LaserPointer」をドラッグ&ドロップします。
するとソースコードが追加され、以下のように「SerializeField」でクラス変数としたものを設定する項目が出てきます。
以下のように「○○Anchor」となっているところに、それぞれ該当する「Anchor」をドラッグ&ドロップします。
次にレーザーを描写するLine Renderderを作成します。
LaserPointerのGame Objectを選択した状態で、「Add Component」ボタンを押してlineを入力して出てきた「Line Renderer」を選択します。
Line Rendererが追加されます。
以下の赤枠で囲った部分を設定します。
Materialの選択は右側にある「○」のようなマークをクリックし、出てきたウインドウで「sp」と入力し「Sprites-Default」を選択します。
レーザーの距離による太さは、以下のようにグラフ上で「ダブルクリック」することで頂点を追加できるので、追加した頂点をドラッグで移動させます。その後その頂点から伸びている薄い線の先にある点をドラッグして曲線を調節します。
レーザーの色や不透明度は、以下のように上下の両端にあるスライダーのチェック部分をクリックで選択し、下側は色、上側はアルファ値を設定します。色やアルファ値は適当でよいです。
必要な設定が済んだら、Line Rendererを「Laser Pointer Renderer」にドラッグ&ドロップします。
これでコントローラーの先からレーザーポインターが出ます。
ちなみにこの状態でビルドしてOculus Goで実行すると以下のようになります。
5:Oculus Goコントローラーのボタン取得方法
Oculus Goのコントローラーの各ボタンは以下のページから確認できます。
developer.oculus.com
ボタンの解説画像のみは以下の通り。
画像の通り各ボタンの名前は以下のようになっています。(間違っている可能性あり)
取得ボタン | 変数名 |
---|---|
トリガー | OVRInput.Button.PrimaryIndexTrigger |
タッチパッドのクリック | OVRInput.Button.PrimaryTouchpad |
タッチパッドの上方向スクロール | OVRInput.Button.Up |
タッチパッドの下方向スクロール | OVRInput.Button.down |
タッチパッドの左方向スクロール | OVRInput.Button.left |
タッチパッドの右方向スクロール | OVRInput.Button.right |
バックボタン | OVRInput.Button.Back |
右手・左手のどちらの設定になっているかは以下で取得できます。
var controller = OVRInput.GetActiveController(); if (controller == OVRInput.Controller.RTrackedRemote) { // 右手の場合 } else if (controller == OVRInput.Controller.LTrackedRemote) { // 左手の場合 }
各種ボタンの基本的な取得方法は以下のようになります。(間違っている可能性あり)
bool result = OVRInput.Get({ボタン変数名}); // ボタンが押されている間ずっとTrueを返す bool result = OVRInput.GetDown({ボタン変数名}); // ボタンが押された時の1回のみTrueを返す bool result = OVRInput.GetUp({ボタン変数名}); // ボタンが離された時の1回のみTrueを返す
タッチパッド上の2次元座標は以下のように取得します。
Vector2 vector = OVRInput.Get(OVRInput.Axis2D.PrimaryTouchpad, OVRInput.Controller.RTrackedRemote); float x = vector.x; float y = vector.y;
6:Oculus Goコントローラーのボタンでレーザーポインター先のオブジェクトを操作する
4まででコントローラーからレーザーポインターが出るようになりました。
5の内容を踏まえて、レーザーポインターの先にあるオブジェクトをボタンで操作できるようにしてみます。
今回は単純にレーザーポインターが当たっている先のオブジェクトの大きさをボタンで変更できるようにしてみます。
方法は簡単でScriptsフォルダの中にある「LaserPointer」を開いて以下のように書き換えます。
using System.Collections; using System.Collections.Generic; using UnityEngine; /** * レーザーポインターを出すクラス */ public class LaserPointer : MonoBehaviour { [SerializeField] private Transform _RightHandAnchor; // 右手 [SerializeField] private Transform _LeftHandAnchor; // 左手 [SerializeField] private Transform _CenterEyeAnchor; // 目の中心 [SerializeField] private float _MaxDistance = 100.0f; // 距離 [SerializeField] private LineRenderer _LaserPointerRenderer; // LineRenderer // コントローラー private Transform Pointer { get { // 現在アクティブなコントローラーを取得 var controller = OVRInput.GetActiveController(); if (controller == OVRInput.Controller.RTrackedRemote) { return _RightHandAnchor; } else if (controller == OVRInput.Controller.LTrackedRemote) { return _LeftHandAnchor; } // どちらも取れなければ目の間からビームが出る return _CenterEyeAnchor; } } void Update () { var pointer = Pointer; // コントローラーを取得 // コントローラーがない or LineRendererがなければ何もしない if (pointer == null || _LaserPointerRenderer == null) { return; } // コントローラー位置からRayを飛ばす Ray pointerRay = new Ray(pointer.position, pointer.forward); // レーザーの起点 _LaserPointerRenderer.SetPosition(0, pointerRay.origin); RaycastHit hitInfo; if (Physics.Raycast(pointerRay, out hitInfo, _MaxDistance)) { // Rayがヒットしたらそこまで _LaserPointerRenderer.SetPosition(1, hitInfo.point); /* ---以下追加した部分--- */ // ヒットしたオブジェクトを取得 GameObject obj = hitInfo.collider.gameObject; // ヒットしたオブジェクトのScaleを取得 Vector3 scale = obj.transform.localScale; if (OVRInput.GetDown(OVRInput.Button.PrimaryIndexTrigger)) { // トリガーボタンを押した時 Vector3 maxScale = new Vector3(5f,5f,5f); // スケールの各値が5より小さい場合は0.1大きくする if (scale.sqrMagnitude < maxScale.sqrMagnitude) { obj.transform.localScale = new Vector3 (scale.x + 0.1f, scale.y + 0.1f, scale.z + 0.1f); } } else if (OVRInput.GetDown(OVRInput.Button.PrimaryTouchpad)) { // タッチパッドボタンを押した時 Vector3 minScale = new Vector3(0.5f,0.5f,0.5f); // スケールの各値が0.5より大きい場合は0.1小さくする if (scale.sqrMagnitude > minScale.sqrMagnitude) { obj.transform.localScale = new Vector3 (scale.x - 0.1f, scale.y - 0.1f, scale.z - 0.1f); } } /* ---追加した部分ここまで--- */ } else { // Rayがヒットしなかったら向いている方向にMaxDistance伸ばす _LaserPointerRenderer.SetPosition(1, pointerRay.origin + pointerRay.direction * _MaxDistance); } } }
このように書き換えると、以下のようにオブジェクトにレーザーポインターに当たった状態でトリガーボタン or タッチパッドボタンを押すとオブジェクトを大きくしたり、小さくしたりできます。レーザーポインターの先にオブジェクトが存在しない場合は、ボタンを押しても何も起こりません。
以上、長々となってしまいましたが、Oculus Goコントローラーの表示方法とボタン取得方法でした。
これでOculus Goコントローラーのボタンなどを取得できるようになったので、色々アプリでボタン操作を実装することができます。
楽しみが広がりますね。
・参考資料