ViveFocusとUnityで作るVRアプリにコントローラを実装してみよう

#はじめに
インフラ整備のつもりでこの記事書いてるんですけどOculusGoとMirageSoloが普及した現代日本において年内発売のViveFocusが介入する余地はあるんでしょうか。
あとなんかストアに5000円ぐらいする強気な値段設定のアプリがハイライトされてて魔窟感があります。
![shot2.png](https://qiita-image-store.s3.amazonaws.com/0/256231/75e74496-2850-b85f-2a78-856224bc95a7.png)
#この記事の内容

基本的にViveFocusのコントローラ周りについて解説します。
ViveFocusでビルドができることが前提条件です。(ビルド周りの記事は[前回](https://qiita.com/Hirai0827/items/8cf92ea9ea42b62e178e)書きました)
サンプルのシーンを覗けば大体わかるようになってるので需要があるかは謎です。
#1.コントローラをシーンに置こう
WaveSDKの中に置くだけで動くいい感じのコントローラがあるのでそれを使いましょう
##1.1.カメラを設置する
WaveVR/Prefabs/WaveVRをシーン上に置く（[waveVR]じゃなくてwaveVRの方です）
![キャプチャ21.PNG](https://qiita-image-store.s3.amazonaws.com/0/256231/9c3dc1aa-0c9e-2e80-4906-6bdfd19d8988.png)
##1.2.コントローラを設置する
ControllerModel/Finch/Resources/Controller/WVR_CONTROLLER_FINCH3DOF_1_0_MC_RとWVR_CONTROLLER_FINCH3DOF_1_0_MC_Lをシーン上に置きます。
![キャプチャ22.PNG](https://qiita-image-store.s3.amazonaws.com/0/256231/00d3aeb7-e6ad-c114-2b49-e400a5754105.png)

Focusの設定で「利き手」に設定されているほうのコントローラだけ表示されますので左右両方置いておきましょう。
(HTC製のスマートフォンを逆側の手のコントローラとして使える機能がついているらしいのですがHTC製のスマートフォンなんて持ってるわけないので実機検証できませんでした…)
この時設置したコントローラの座標が実際の挙動に影響する（Positionをずらせばコントローラの基準位置もずれる）ので調整しましょう。
デフォルトでは右手側は(x,y,z) = (0.2,-0.7,0)、左手側は(x,y,z) = (-0.2,-0.7,0)みたいです。
##1.3.試しにビルドしてみる
カメラとコントローラはいい感じに動くと思います。
#2.コントローラからデータを取得しよう
コントローラやHMDからデータを取得できなければいい感じに動くコントローラもただの飾りになっちゃいますので試しにデータをとってみましょう。
コントローラの入力についてのサンプルシーンを作ったので使ってください。
[githubへのリンクです](https://github.com/Hirai0827/ViveFocusControllerDebug)
![shot4.png](https://qiita-image-store.s3.amazonaws.com/0/256231/55d7d261-dd1e-ee3b-9984-3dc4fb7e08a6.png)

##2.1.HMDのデータを取得する
Unity.VRでは取得できないのでWaveVR側の物を使います。
WaveVRSDKの機能を使うときは`using wvr;`です。
`WVR_DeviceType`クラスはデータの取得先を指定するものです。（例えば「HMD」「右手のコントローラ」など）
`WaveVR.Device` は実機の情報を格納するクラスです。
`WaveVR.Instance.getDeviceByType(WVR_DeviceType)`で実機をサーチしてWaveVR.Deviceに代入することができます。
つまり
`public WVR_DeviceType type;
 WaveVR.Device device = WaveVR.Instance.getDeviceByType(this.type);`としてUnityのインスペクタから任意のtypeを選択すれば変数devideにコントローラやHMDの情報が代入可能ということになります。
さらに`device.rigidTransform.pos`とすればデバイスの座標、`device.rigidTransform.rot`とすればデバイスの角度を取得することができます。先ほどのtypeでHMDを指定すればHMDの座標や角度を取得することができます。
##2.2.コントローラのデータを取得する
キー入力や角度の取得ができます。タッチパッドはAxisで取れます。
###2.2.1.コントローラの角度を取得する
角度は2.1でやったHMDのときと同じです。座標の取得は現在は不可能みたいです。今後のアップデートで画像認識を使った6軸対応をするそうなので楽しみにしておきましょう。
###2.2.2.ボタン入力を取得しよう
キー入力についてですが、基本的に
`WaveVR_Controller.Input(type).GetPress(buttonId)`で行います。
GetPressのほかにGetPressDownやGetPressUpも使うことができます。
この時のtypeは先ほどのWVR_DeviceTypeであり、
buttonIdには以下の変数を代入できます。
`        WVR_InputId.WVR_InputId_Alias1_Menu,
        WVR_InputId.WVR_InputId_Alias1_Grip,
        WVR_InputId.WVR_InputId_Alias1_DPad_Left,
        WVR_InputId.WVR_InputId_Alias1_DPad_Up,
        WVR_InputId.WVR_InputId_Alias1_DPad_Right,
        WVR_InputId.WVR_InputId_Alias1_DPad_Down,
        WVR_InputId.WVR_InputId_Alias1_Volume_Up,
        WVR_InputId.WVR_InputId_Alias1_Volume_Down,
        WVR_InputId.WVR_InputId_Alias1_Touchpad,
        WVR_InputId.WVR_InputId_Alias1_Trigger,
        WVR_InputId.WVR_InputId_Alias1_Bumper,
        WVR_InputId.WVR_InputId_Alias1_System`
変数名を見ればどれがどのボタンに対応しているのかは大体わかると思いますが、一つ注意すべき点は、ViveFocusのトリガーは内部値的にはBumperである点です。Triggerでは取得できません。
ちなみにDpad_(方向)でタッチパッドのどの辺が押し込まれたかを取得することができます。実用的ですね。
###2.2.3.タッチパッドの情報を取得しよう
タッチパッドでは
- タッチしたか否か
- 押し込んだか否か
- 触れている部分のx,y座標(Vector2)(-1≦x≦1,-1≦y≦1)
を取得することができます。上からそれぞれ
- `WaveVR_Controller.Input(device).GetTouch(WVR_InputId.WVR_InputId_Alias1_Touchpad)`
- `WaveVR_Controller.Input(device).GetPress(WVR_InputId.WVR_InputId_Alias1_Touchpad)`
- `WaveVR_Controller.Input(device).GetAxis(WVR_InputId.WVR_InputId_Alias1_Touchpad)`
で取得することができます。注意すべき点としては、ViveFocusのタッチパッドは円形なのでxとyはその円内しか動けないということです。（つまり0≦x^2 + y^2≦1であり、(x,y) = (1,1)みたいな感じにはならない）
#3.コントローラにくっついてくるインジケータを変更しよう
ところでこの標準コントローラにはデフォルトで操作説明のUIがついています。デフォルトではボタンの説明ですが、Unity上のインスペクタを弄るだけで簡単に文面を変えられるので便利。例えばトリガーの部分に「Shot」、タッチパッドに「Menu」などアプリ固有のガイドを簡単につけることができます。いいですねコレ。OculusGoとかにも標準搭載してほしいです。
##3.1.実際に変更してみよう
WVR_CONTROLLER_FINCH3DOF_1_0_MC_R(L)の子オブジェクトのMIA_CtrlについているコンポネントであるWave_VR_Show Indicatorの中にIndicationという配列があるはずです。
その中のIndicationTextの文面を変更すると、変更した通りの表示になります。`'system'`だとデフォルトの文面になるみたいです。
![キャプチャ20.PNG](https://qiita-image-store.s3.amazonaws.com/0/256231/95245831-c0a0-10fa-671c-9c6ae1090b8a.png)
こんな感じ。日本語も行けちゃう。
![shot3.png](https://qiita-image-store.s3.amazonaws.com/0/256231/e2e44176-ba17-b459-0fb6-fde3a7b879f0.png)
#さいごに
ドキュメントがないんだよね（笑う）
なんかよさげな記事（とくにAR周り）見つけたら教えてください。
次回はコントローラの振動とスクリーンショット、キャプチャ周りをやるかも？（技術力が足りていれば）