Unity2019.3 XR Plug-in ManagementによるVRプロジェクト初期導入

## 概要
Unity5.6の頃に作成したプロジェクトをリフレッシュするにあたり
「Unity2019.3でXR Plug-in ManagementによるVRプロジェクトを立ち上げて手を表示、動かす」までの導入部分を調べてやってみました。

~~先人の情報(下記URL等)を多少読み替えて適用可能な部分も多いですが、Unity2019.3ではUnityの**VRサポート**は廃止予定となり**XR Plug-in Management**による導入が推奨されていたりして、如何せん古い情報なのでそのままではうまくいかないこともありまとめておきました。
https://framesynthesis.jp/tech/unity/xr/
https://qiita.com/urahimono/items/7a9601e692e53ee4318f~~

2021/11訂正します。フレームシンセシスさんの情報は更新され詳細書かれています.
この記事は古いので以下のページを参考にすることを推奨します。
https://framesynthesis.jp/tech/unity/xr/


## 開発環境
Windows10 Pro + Unity 2019.3
VR環境なし

## 実行環境
Windows10 Pro
OculusHome(開発者モードON)
Oculus Rift CV1 + Oculus Touch

## 使用APIと使いそうなパラメータ羅列
- [XRDevice](https://docs.unity3d.com/ja/2019.3/ScriptReference/XR.XRDevice.html)
   - isPresent (bool)  XRデバイスあるかないか
   - model (string) HMDのモデル名
   - refreshRate 画面のリフレッシュレート
   - SetTrackingSpaceType  座位かルームスケールか
- [XRNode](https://docs.unity3d.com/ja/2019.3/ScriptReference/XR.XRNode.html)  
ID0~5はUnityEngine.XRに含まれる **Tracked Pose Driver** をアタッチすることでスクリプトを書くことなく利用できる（後述）。  
```
   0: XRNode.LeftEye
   1: RightEye
   2: CenterEye
   3: Head
   4: LeftHand 
   5: RightHand ```

- [InputTracking](https://docs.unity3d.com/ja/2019.3/ScriptReference/XR.InputTracking.html)
   - GetTrackedNodeStates(List<[XR.XRNodeState](https://docs.unity3d.com/2019.3/Documentation/ScriptReference/XR.XRNodeState.html)>)   
   [Trackerを使う場合のposやrotの取得（ようてん様の夢VTuber）](https://github.com/youten/YVTuber/blob/master/Assets/YVTuber/Script/XRDeviceTracker.cs)
       - .position (vector3)
       - .rotation (Quaternion)
       - .tracked(bool)
   - GetLocalPosition(Node1,Node2) 廃止予定(こりん様の記事で使用)
   - GetLocalRotation(Node1,Node2) 廃止予定 〃

- [Touchのボタン・軸入力表](https://docs.unity3d.com/2018.3/Documentation/Manual/xr_input.html)
   - TRIGGER L:14 R:15 など。私はレガシーの入力で使っています
   - GRIP L:4 R:5
- アセット
   - SixenseUnityPlugin  
   手モデルとアニメが入っている。DemoScenes/Modelsをインポートする。  
   [使い方の参考](https://qiita.com/noitak/items/4463ef7fa9afc2ff2c79) 

## VRシーンの初期作成手順
1. プロジェクトを作成
1.  *プロジェクト設定 > XR Plug-in Management* よりOculusとMockHMDLoaderを選択して導入（開発環境にはOculus無いのでMockも入れた）
1. シーン名をSampleから適宜変更
1. ヒエラルキー右クリックメニュー **XR > Convert Main Camera to XR Rig** 実行 
Main CameraがXR Rigのツリー下に入り、Main Cameraに**Tracked Pose Driver**がアタッチされる。
   - Main Camera のニアクリップは初期0.3だと大きすぎるので0.02程度に設定
   - 視野角はお好みで。初期60は狭いので90くらいあってもいい
1. **Camera Offset**の下に空のオブジェクト**RightHand**を作成
   - **RightHand**に**Tracked Pose Driver**コンポーネントを検索しアタッチ
   - **Tracked Pose Driver**/Deviceを Generic XR Controller に設定
   - **Tracked Pose Driver**/Pose Sourceを Right Controller に設定
1. 手のモデル SixsenceInput/Demoscenes/Models/Hand をRightHand以下に配置
   - **Hand**/Animator/ControllerにSixsenceHandAnimatorを設定
1. **RightHand**をコピーして名前を**LeftHand**に変更。
   - **RightHandとLeftHand**/Transform/位置をそれぞれ X:0.3 X:-0.3程度ずらし離す
   - **Tracked Pose Driver**/Pose Sourceを Left Controller に設定
   - **LeftHand**のTransform/拡大縮小のX: -1に設定。モデルを反転させる。
   - **Hand**/Transform/位置 Z:-0.05程度下げてTouchコントローラに合わせる
   - **Hand**/Transform/回転 Z rot:+-90度 させて外側に向けTouchと向きを合わせる

1. 手のアニメーションコントローラスクリプトは別途作成し左右の**Hand**にアタッチ

```c#
//InputManagerクラスは自作なので、適当にJoyButtonの取得に読み替えてね
    void Update()
    {
        if (InputManager.ActButtonStatus["Right-Trigger"] && InputManager.ActButtonStatus["Right-Grip"])
        {
            // トリガとグリップ同時で握る
            _animator.SetBool("Idle", false);
            _animator.SetBool("Point", false);
            _animator.SetBool("Fist", true);
            _animator.SetFloat("FistAmount", 1.0f);
        }
        else if (!InputManager.ActButtonStatus["Right-Trigger"] && InputManager.ActButtonStatus["Right-Grip"])
        {
            // 指さす
            _animator.SetBool("Fist", false);
            _animator.SetBool("Point", true);
            _animator.SetBool("Idle", false);
        }
        else
        {
            // 開く
            _animator.SetBool("Fist", false);
            _animator.SetBool("Point", false);
            _animator.SetBool("Idle", true);
        }
    }
```

手順は以上.画像は暇な時に付ける

## ビルド
VRハードウェアがない環境でビルドした出力をOculusRift CV1のある環境へコピー。
実行すると、Touchの位置に手が見えてトラッキングされました。:laughing: 
後継のRiftSやQuest対応の為か、トラッキングが外れたHandは初期位置に戻らず、トラッキング外れる前の最後の位置に留まるようになっていますね。地味に嬉しい。

以上です