OculusRiftとFinal IKでVTuberになる

# はじめに
OculusのHMD「Oculus Rift S」とUnityの有料アセット「Final IK」で　MMDモデルになりきってアバターを動かす方法と，そのときのポイントや落とし穴について書きました．
Oculus社のHMDなら旧型のRiftやOculus Linkで接続したOculus Questでもまったく同じように動かせると思います．

# 準備したもの
* Oculus Rift S
* Unity (v2019.2.17f1)
* [MMDモデル Kizuna AI](https://kizunaai.com/download/)
* [MMD4Mecanim (20200105 Beta)](http://stereoarts.jp/)
* [Oculus Integration](https://assetstore.unity.com/packages/tools/integration/oculus-integration-82022)
* [Final IK](https://assetstore.unity.com/packages/tools/animation/final-ik-14290?locale=ja-JP)

# とりあえずHMDでMMDを動かしてみる

## 1. Unityで3Dプロジェクトを作成
Unityを起動して新規3Dプロジェクトを作成します．
<img width="722" alt="image01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187083/86c582fd-be6b-fe5f-6f20-aef8ac26faa3.png">

## 2. PMX形式のMMDをUnityにインポート
好きなMMDを用意してください．個人利用であれば[ニコニ立体](https://3d.nicovideo.jp/)や[BOOTH](https://booth.pm/ja)，企業VTuberの公式サイトなど様々なところで色々配布されているものを使えると思います．この記事では例として「[キズナアイのMMD](https://kizunaai.com/download/)」を利用させていただこうと思います．

<div align="center"><img width="221" alt="kizunaai.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187083/806c0657-f6bf-6208-397b-51c3e667b26f.png"></div>
Kizuna AI ver1.01　© Kizuna AI

配布されている3Dモデルデータは一般に```.pmx```という形式が多いですが，Unityで読み込むことができるのは```FBX```という形式なので```PMX```を```FBX```に変換する必要があります．MMDを変換するために[Nora](https://twitter.com/Stereoarts)さんが公開しているMMD4Mecanimを使用します．MMD4Mecanimを[ダウンロード](http://stereoarts.jp/MMD4Mecanim_Beta_20200105.zip)してzipファイルを解凍し,「MMD4Mecanim.unitypackage」をドラッグアンドドロップでUnityにインポートしてください．
<img width="720" alt="image02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187083/48f6075e-193d-6f7e-bd2e-2d429be42296.png">

次にUnityのProjectウィンドウから```PMX```形式のMMDをまるごとドラッグアンドドロップでAssetsに追加します．MMD4Mecanimによって```PMX```ファイルがあるのと同じ階層に自動で```.MMD4Mecanim.asset```というファイルが生成されると思います．
<img width="720" alt="image03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187083/67844373-97bf-2cfc-c620-a32ac1fefe78.png">

この```.MMD4Mecanim.asset```をクリックしてInspectorウィンドウからProcessボタンをクリックすると変換が行われます．（その前にMMDの利用規約に同意する必要がある場合があります．）フォルダの同じ階層に```FBX```ファイルができていればUnityへのMMDのインポートは完了です．
<img width="720" alt="image04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187083/a9c5cd16-7c7f-6cc4-679e-2d92534c8a1c.png">

このPrefabをHierarchyウィンドウにドラックアンドドロップすることでシーンにモデルを配置しておきます．
<img width="720" alt="image05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187083/5a53621b-5a04-2b82-98c3-10cc5170f547.png">

最後にインポートしたモデルをFinal IKで制御するためにAssets下にあるMMDのPrefabを選択してInspectorウィンドウの Rig > Animation Type を```Humanoid```に変更してApplyを押します．
<img width="720" alt="image08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187083/cc6d6844-390a-f06c-a67d-ffef9b39edd4.png">

## 2.5. [余談] 自作MMDを使う
この投稿ではモデルの自作については触れませんが，モデルを自作する方法としてはBlenderなどの無料モデリングソフトでフルスクラッチで作るという高い技術を求められるやり方以外にも，最近は[Vroid Studio](https://vroid.com/studio/)などの比較的簡単に作れるツールが充実してきていると思います．
ちなみに，Blenderで自作した場合には```FBX```形式で出力できるため上述のMMD4Mecanimによる変換は必要ありません．また，Vroid Studioは```.vrm```で保存することになるため，[UniVRM](https://github.com/vrm-c/UniVRM/releases)を利用してUnityにインポートする必要があります．

## 3. Oculus Integrationの導入
UnityでOculusのHMDを使用するためにOculusからUnity Asset Storeで公開されている[Oculus Integration](https://assetstore.unity.com/packages/tools/integration/oculus-integration-82022)を導入します．
今回はUnity 2019内のAsset StoreからOculus IntegrationをImportします(Unity 2020ではインポートの方法が若干変わっています)．
<img width="720" alt="image06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187083/ab43bb88-085d-7798-35b4-cf89ef344276.png">
<img width="720" alt="image07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187083/1abbef48-45a7-6367-e6fe-3f1e5c2698b3.png">

次にインポートしたOculus Integrationの中から Assets > Oculus > VR > Prefabs にある```OVRCameraRig```をSceneに配置します．これがHMD用のカメラになります．HMD用のカメラを配置したので元々あったMain Cameraは削除して問題ありません．
<img width="720" alt="image09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187083/e8fd4b0d-fb86-ae2d-d4f7-697dc2616778.png">

## 4. Final IKの導入と設定
Oculus Integrationのときと同様にAsset StoreからFinal IKをダウンロードしてインポートします．
<img width="720" alt="image10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187083/571eacc5-75f7-2381-f0c7-fe96b29d6dc9.png">

Assets > Plugins > RootMotion > FinalIK > IK Components > VRIK.cs をSceneに配置したキズナアイのPrefabにアタッチします．
<img width="720" alt="image11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187083/bea6fd1f-8fef-4da0-442b-58665771377a.png">

Sceneの OVRCameraRig > Tracking Space の中にあるCenterEyeAnchor，LeftHandAnchor，RightHandAnchorそれぞれの中にEmpty Objectを作成します．トラッキングスペースの中に配置したこのオブジェクトをVRIKでモデルにトラッキングさせることでモデルを動かします．空オブジェクトの名前はHeadTarget，LeftHandTarget，RIghtHandTargetとしました．
<img width="720" alt="image12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187083/5d27abb9-750c-bdcb-485f-fd384737efb2.png">

作成したターゲットの空オブジェクトをモデルにアタッチしたFinal IKのスクリプトにアタッチします．
<img width="720" alt="image13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187083/c733d07b-4fbd-332d-1b89-f99e21452b0e.png">

ここまででHMDの頭と両手に追従してMMDを動かすことができます．

# いろいろ設定していく
## 視点を合わせる
HMDを装着した人とアバターの顔の視点を合わせます．
OVRCameraRigのInspectorから OVRManager > Tracking > Tracking Origin Type を```Eye Level```から```Floor Level```に変更します．
HMDはアプリケーション実行時に本体の高さを取得します．その後，Eye Levelでは**HMDの位置を原点**(高さ0)としてSceneを配置します．これは空からVR空間を見下ろす場合など使用者の身長にかかわらず同じ高さにカメラを置きたいときなどにカメラのオフセットを高くするなどしてよく使用します．一方でFloor Levelでは**足元を原点**(高さ0)にSceneを配置します．これは本記事のようにMMDになりたい場合など使用者が地面に接地している場合によく使用します．
<img width="389" alt="image14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187083/d343e9a6-3ff4-7886-1ff7-b7fb22289adc.png">

## 身長を合わせる
自分の身長とMMDの身長（腕の長さや腰の高さなど）が大体同じくらいになるようにMMDのInpsectorからScaleを変更します．この辺りは実際にHMDを装着してGame Viewで見ながら合わせるとやりやすいと思います．
<img width="380" alt="image15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187083/ad4bd3ac-5db4-9675-5b7c-ccdae685ebb6.png">

## レンダリング範囲の設定
現在の状態で実行するとMMDの顔の内側まで表示されてしまい，場合によっては結構グロテスクな映像になってしまいます．そこで OVRCameraRig > TrackingSpace > CenterEyeAnchor のInspectorから Camera > Clipping Planes のNearを0.15程度に設定します（MMDによって適当な値に変更してください）．これでカメラから0.15以内のオブジェクトは表示されなくなり，MMDの顔を内側から覗くことはなくなります．
<img width="390" alt="image16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187083/8cba7b41-8d95-fd5f-f773-245a6d74f916.png">

## パラメータ調整
手の角度を調整します．キズナアイのMMDはこのままだと手の角度がおかしいので，左手のターゲットのRotation-Yを90度，右手のターゲットのRotation-Yを-90度に変更します．
<img width="391" alt="image17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187083/f6c12723-68bd-a145-a235-687d1e3239d3.png">

以上で，Unityからプロジェクトを実行するとHMDでキズナアイを動かせるようになりました．

# おまけ
## 自分の姿を見る
自分の姿を客観的に観測したい場合は，OVRCameraRigの中のCenterEyeAnchorがHMDの視点なので，これを現在のHMDの頭と重なった状態から角度を180度回して少し前に出せば良いです．
<img width="388" alt="image19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187083/31edbdb6-1aa6-97d6-df32-e0ad0eef3755.png">

<img width="704" alt="image18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187083/1b10ecd0-82eb-fd8f-110e-19224f61fc36.png">

## 指の制御
[OculusFinger](https://gist.github.com/nryota/1bff13989d3c501249ae93ca46dc9287)というMMDの指にアタッチするだけでコントローラのボタン入力で指を動かせるスクリプトが開発されています．詳細は省きますが，解説付きなので読みながら回転角を調整してあげれば指も動かせるようになりました．

# おわりに
Final IKを用いると簡単にMMDの制御ができました．
いろいろなサイトを参考にさせていただいた結果，投稿内容の前半は何番煎じか分からないようなものになってしまいそうになりましたがここからフルトラじゃなくてももっと自然な動きを追求していきたいところです．

# 参考にさせていただきました
* [Oculus LiftとFinalIKを使ってバーチャルYoutuberになる方法](https://qiita.com/ngron/items/f90ace8cb84f3aebaa5f)
* [VR IKでVRコスプレをする時のハマり所とソリューション(Oculus Rift想定)](https://qiita.com/karin_tsvr/items/dddc154c893be2911a36)
* [https://qiita.com/_karukaru_/items/b74bb5bdf08f5de32d0e](https://qiita.com/_karukaru_/items/b74bb5bdf08f5de32d0e)
* [【Unity】【Oculus Quest】VRにおけるカメラ座標の設定方法まとめ](https://light11.hatenadiary.com/entry/2019/11/05/220200#Oculus-Quest%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E3%82%AB%E3%83%A1%E3%83%A9%E5%BA%A7%E6%A8%99%E3%81%AE%E6%B1%BA%E5%AE%9A%E3%83%95%E3%83%AD%E3%83%BC)
* [Oculus TouchでUnityちゃんの指を動かして遊ぼう](http://eyln.hatenablog.com/entry/2016/12/19/003435)