Oculus Go で手のモデルを表示する

気分を出すために、Oculus Go 標準のコントローラーの代わりに手のモデルを表示して動かしてみます。
![out2.gif](https://qiita-image-store.s3.amazonaws.com/0/241491/a0e136e0-ec7b-4563-a6ea-b17896e02f81.gif)


参考にしたのは次の記事です。

* [手のモデルと透明にする方法](http://zabaglione.info/archives/829)
* [VRで手のモデルを使いたい](http://bibinbaleo.hatenablog.com/entry/2018/03/08/220959)

## 環境
* Unity 2017.4.4f
* Oculus Integration 1.25

Oculus Go 開発の最小環境は以下の記事を参照してください。本記事では基本的な設定は完了しているものとします。

[Windows上のUnityでOculus Goアプリ開発するまでの最短手順](https://qiita.com/TyounanMOTI/items/fc11cb0c15f62ec88817)

## 手のモデルを表示する
参考記事にある無料アセットを使わせてもらいます。

[SixenseUnityPlugin](https://www.assetstore.unity3d.com/jp/#!/content/7953)

1. アセットをImport します。手のモデルだけあれば良いので、Models にだけチェックを入れればOK。
![gohand-01.png](https://qiita-image-store.s3.amazonaws.com/0/241491/a9cc3e93-f49a-5a9f-b144-14474d2c6a43.png)

2. Hierarchy にOVRCameraRig を配置する（元のMainCamera は削除）
3. OVRCameraRig/TrackingSpace/LeftHandAnchor とRightHandAnchor 以下にProject View の「Oculus/VR/Prefabs/TrackedRemote」を配置する
  * LeftHandAnchor 以下に配置した方はInspector で「Controller」の値を「L Tracked Remote」に変更
4. 左右のTrackedRemote 以下にSixenseInput/DemoScenes/Models/Hand を配置する
  * アセット付属のHand モデルは右手タイプなので、左手側は左右反転させます。左手(LeftHandAnchor 以下に配置した方)のInspector で「Transform > Scale > x」を「-1」に設定します。「両手が右手ごっこ」をしたい場合は省略してください。
  * 元からあったGearVrControllerModel とOculusGoControllerModel は削除します。しないとずっと表示されます。
5. TrackedRemote のInspector で「Model Oculus Go Controller」に、子オブジェクトのHand を設定する
  * Gear VR 対応を考えない場合は「Model Gear Vr Controller」は未設定でOK
  * Gear VR 用を設定する場合は、**Hand オブジェクトを複製するなどしてもう一つ用意して、Oculus Go 用とは別のオブジェクトを設定してください**。OVRTrackedRemote スクリプト内で機種判別フラグを見て表示/非表示が切り替わるので、同じオブジェクトを参照させるとおかしなことになります。「どうせ同じ手を表示するだけだから」と何も考えずに一つのオブジェクトを設定してハマったアカウントはこちらになります。

ここまでで、基本的な表示と動作は完了です。Hierarchy View は以下のようになります。
![gohand01a.png](https://qiita-image-store.s3.amazonaws.com/0/241491/4ea7e9d1-c580-c370-a943-ed07c673eca5.png)


### 半透明表示にする
アセットのままだとごつい感じのリアルハンドなので、参考記事にもあるようにVRっぽく(?)半透明表示にしてみます。

1. Project ビューでCreate > Material を選択し、マテリアルを追加する
「GhostHand」という名前にしました。

2. Rendering Mode は「Transparent」、Albedo を適当に青白く、Alpha を半分くらいにする
![gohand-06.png](https://qiita-image-store.s3.amazonaws.com/0/241491/54df96d9-8d3b-0b9f-e5c0-7f6374eb4667.png)

RGBAは様子を見ながら、お好みで適当に調整してください。Emission をつけてもいい感じになります。
3. Hand オブジェクト下の「Hand_MDL」にマテリアルを反映する
![gohand02.png](https://qiita-image-store.s3.amazonaws.com/0/241491/7bb559f4-0432-ec74-cb91-ce7345a49731.png)


### アニメーションを追加する
アセットSixenseUnityPlugin には基本的な手のアニメーションが付属しているので、これを使用します。アニメーションを遷移させるためのパラメータが設定されているので、スクリプトでフラグを制御すればOK。パラメータは次の通りです。

|パラメータ名|型|動作|
|:--|:--|:--|
|GripBall|bool|ボールを握る(バスケットボールくらいの大きなボールの印象)|
|Fist|bool|握る（FistAmount の値で握り度合いを調整）|
|HoldBook|bool|本を持つ（親指と他の指が向かい合う感じ）|
|Idle|bool|デフォルト。軽く開いた手|
|Point|bool|人差し指で指差し確認|
|FistAmount|float|握り度合い（Fistと連動。0～1で、1が最も閉じる）|
|TriggerReleased|bool|？|

1. AnimatorController を追加する
Hand オブジェクトのInspector でAnimator > Controller にSixenseInput/DemoScenes/Models/SixenseHandAnimator をドラッグアンドドロップして設定します。
![gohand03.png](https://qiita-image-store.s3.amazonaws.com/0/241491/323d5ce6-9126-d2ad-6ed2-6d1678a17ef1.png)

反対側のHand も忘れずに。
2. アニメーション制御スクリプトを追加する
コントローラのトリガーボタンを押したら握る動作を実装してみます。新たにスクリプトを作成し、以下を入力したらHand オブジェクトにアタッチします。

``` HandController.cs
using UnityEngine;

public class HandController : MonoBehaviour
{
    Animator _animator;

    void Awake()
    {
        _animator = GetComponent<Animator>();
    }

    void Update()
    {
        if (OVRInput.Get(OVRInput.Button.PrimaryIndexTrigger))
        {
            // 握る
            _animator.SetBool("Idle", false);
            _animator.SetBool("Fist", true);
            _animator.SetFloat("FistAmount", 0.8f);
        }
        else
        {
            // 開く
            _animator.SetBool("Fist", false);
            _animator.SetBool("Idle", true);
        }
    }
}
```

## まとめ
Oculus Go の操作は片手コントローラーですが、手のモデルを表示することで没入感が高まるようなコンテンツの場合には使えそうです。