VIVE Input Utility for UnityでVRアプリをVIVE Focus Plus/PCVR 両対応する。

#はじめに

VIVE Focus Plusでアプリを作るときはVive Wave SDKを使うのが基本ですが、それに加えて[VIVE Input Utility for Unity](https://github.com/ViveSoftware/ViveInputUtility-Unity)を使うことで、 コントローラーの入出力をPCVRにも対応させることが出来ます。これにより、VIVE Focus Plus/PCVR両対応のアプリを作ったり、VIVE Focus PlusのデバッグにVIVEやOculus Riftを使うのが簡単になります。正直、Vive Wave SDKについてくるサンプルより使いやすいのでお勧めです。

公式の情報は、上記のGithubサイトか、少し古いですが[こちらのドキュメンテーション](https://usermanual.wiki/Pdf/guide.2092279436.pdf)をご覧ください。

#プロジェクトのセットアップ
Unity新規プロジェクト(今回はUnity2019.2.2f1を使用）を作ったら、VIVE Input Utilityをアセットストアからダウンロード、インポートしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58503/3594069e-a6f3-8c11-fda4-92262d0b47ee.png)

次に[Vive Wave SDK](https://developer.vive.com/resources/knowledgebase/vive-wave-sdk-3-1-1-unity-beta/)をダウンロード、インポートしてください。今回使うのはWave SDK 3.1.1 (Beta)です。インポートしたら、WaveVRのDefault Preference Dialogを開いて、Accept Allボタンを押してプロジェクトの設定を行ってください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58503/821841ef-14e9-65b3-4b13-afcdae3db593.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58503/34ffffdc-60ab-0a42-9586-307d793102db.png)
すると、ビルドターゲットがAndroidになりますが、コンパイラエラーが出てしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58503/cd8cbad0-93a4-988e-6314-5a5943ab7bbb.png)
これは、コンパイラエラーを起こしているWaveVRModule.csの641行をコメントアウトすればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58503/60cde501-8f0f-b559-66d0-1df000da1787.png)
さらに、Project SettingsのOther SettingsのGraphic APIsでVulkanの選択肢を消してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58503/ab986b7e-498d-79bc-b288-508023658a3a.png)

これでOKです。

#シーンのセットアップ

基本的なシーンのセットアップの方法は、[公式チュートリアル](https://github.com/ViveSoftware/ViveInputUtility-Unity/wiki/Example-0.Tutorial)の通りで問題ありません。Vive Waveでは、通常はVive Wave付属のカメラリグを使いますが、VIVE Input Utilityを使う場合は、そちらに付属のViveCameraRigを使うので注意してください。

#ボタンタッチ、入力

基本的な使い方は以下の通りです。スクリプト本体の一番上に`using HTC.UnityPlugin.Vive;`を入れるのを忘れないでください。

- 右手、タッチパッドのタッチ
`ViveInput.GetPressEx(HandRole.RightHand, ControllerButton.PadTouch)`

- 右手、タッチパッドの押下
`ViveInput.GetPressEx(HandRole.RightHand, ControllerButton.Pad)`

- 右手、コントローラーのメニューボタン押下
`ViveInput.GetPressEx(HandRole.RightHand, ControllerButton.Menu)`

左手の時は`HandRole.LeftHand`となります。ボタンはほかにも`ControllerButton.Trigger`, `ControllerButton.Grip`が使えます。

タッチパッドを触る、押したときの位置はそれぞれ

- `ViveInput.GetPadAxisEx(HandRole.RightHand)`
- `ViveInput.GetPadPressAxisEx(HandRole.RightHand)`

で取得できます。

それぞれの操作に対しては、コールバックを設定することもできます。例えば、

`ViveInput.AddPressDown(HandRole.RightHand, ControllerButton.Trigger,OnPressDown);`

により、右手のトリガーを押下した時にOnPressDownを実行できます。同様に、AddPress, AddPressUp, AddClickも可能です。


取り消すときは以下の通りです。

`ViveInput.RemovePressDown(HandRole.RightHand, ControllerButton.Trigger, OnPressDown);`


# コントローラーの位置、回転

コントローラーの位置、回転はそれぞれ以下の方法で取得します。

- `VivePose.GetPoseEx(HandRole.RightHand).pos`
- `VivePose.GetPoseEx(HandRole.RightHand).rot`

# コントローラーの右手、左手

Vive Focus Plusでは、最初に接続したコントローラーが「右手」の「役割 Role」になります。また、片方しか接続していない場合は、それが「右手」になります。そのため同じコントローラーでも頻繁に「右手」「左手」が入れ替わるため、その変更を検知する必要があります。

これらの状態は、コントローラーのゲームオブジェクトにアタッチされているVive Pose Trackerコンポーネントから参照できます。まず、コントローラーが接続された、解除されたときのイベントは

- `vivePoseTracker.onIsValidChanged.AddListener(UnityAction)`

で取得できます(ここでvivePoseTrackerは、Vive Pose Trackerコンポーネントへの参照を持つ)。ここで与えるUnityActionは`OnRightDeviceEnabled(bool state)`のように、bool型を引数とします。

接続されたときに、コントローラーが右手の役割であるかは

- `vivePoseTracker.viveRole == ViveRoleProperty.New(HandRole.RightHand)`

でわかります。

また、一旦コントローラが接続された後の右手、左手の役割の変更は

- `vivePoseTracker.viveRole.onRoleChangedEx += OnRightDeviceRoleChanged`

で取得できます。この時、与えるメソッド（ここではOnRightDeviceRoleChanged）は

- OnRightDeviceRoleChanged(System.Type previousRoleType, int previousRoleValue)

の形になります。これにより、変更前のRoleがわかるようになっています。RoleTypeの名前が知りたければpreviousRoleType.FullName を使ってください。

#PCVRでの実行

VIVE Input Utilityを使ってVive Focus Plus向けに作ったシーンは、そのままViveやOculus Riftでも実行できます。残念ながら、Oculus Questでは動きません。

Oculus Riftの場合、メニューボタンがAボタンになり、タッチバッドがスティックになるので注意してください。