UnityのVR SamplesのMazeでキャラクターの変更を自動化する

# はじめに
前回記事 [UnityのVR SamplesのMazeでキャラクターを変更する]
(https://qiita.com/Satoshi_Takahama/items/c95227acf3456eb2255d) の続きです。
前回、キャラクターを変更する際に、変更する箇所が多く結構手間がかかっていたため、
VRMのファイルを配置するだけで動作できる仕組みを検討し、実装してみました。
今回はソースコードをGitHubに置いています。
また、簡単に試せるように、unitypackage形式のファイルも置いています。
(2019/09/10追記)
Oculus Integration for Unity - 1.40に更新しました

#開発環境
Unity 2019.2.0f1
VR Samples - 1.4
Oculus Integration for Unity - ~~1.39~~ 1.40
UniVRM v0.53.0
「ニコニ立体ちゃん」(VRM版)

#ビルド手順
GitHubに置いたunitypackage形式のファイルでの手順を説明します。
1. 3Dで新規プロジェクトを作成します。
2. Build Settings から Platform を Android に Switch Platformします。
3. Oculus Integrationをアセットストアからダウンロードし、インポートします。インポートには数分時間がかかります。
4. VRM形式のモデルのファイルを読み込むためのアセットUniVRMを[vrm-c/UniVRM](https://github.com/vrm-c/UniVRM/blob/master/README.ja.md) からダウンロードし、インポートします。自分がダウンロードしたファイルは"UniVRM-0.53.0_6b07.unitypackage"ですが、数字の部分はバージョンにより変わります。
5. GitHubの[VRSamplesMaze](https://github.com/SatoshiTakahama/VRSamplesMaze) からVRSamplesMaze.unitypackageをダウンロードし、インポートします。
6. Player Settings... から以下の項目を変更します。
	6-1. Other Settings -> RenderingのAuto Graphics APIにチェックをいれます。Identification の Package Nameを適当に変更し、Minimum API Levelは21以上に設定します。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215278/29cddb7e-04b9-da9f-7f0d-662963fb0419.png)

 6-2. XR Settings -> Virtual Reality Supported にチェックをいれ、Virtual Reality SDKs の + を押して、Oculus を選択します。
![XRSettings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215278/57f5ac26-c04b-b45a-bcd8-f1c3f13b1ca2.png)
7. VR SamplesのシーンMazeを開きます。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215278/70bad153-69f0-5442-8800-8413c0a95af5.png)
8. OVRCameraRigのTarget DevicesをQuestに変更します。![OVRCameraRig.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215278/740f955e-78f6-0ef7-9bf0-28510b61b068.png)
9. AndroidManifest.xmlを再生成します。メニューのOculus->ToolsからRemove AndroidManifest.xmlを選択します。次に、Oculus->ToolsからCreate store-compatible AndroidManifest.xmlを選択します。
10. UIの設定に使用するスクリプトを一部修正します。Assets\Oculus\SampleFramework\Core\DebugUI\ScriptsにあるDebugUIBuilder.csのtransformを更新している箇所をコメントアウトします。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215278/3f6c6f3b-e506-44c4-3f81-27a9617cbab2.png)
11. 次に、キャラクターのファイルを[ニコニ立体ちゃん (VRM)](https://3d.nicovideo.jp/works/td32797) からダウンロードします。
12. Projectウインドウで、Assetsフォルダの下にキャラクターを配置するフォルダ(今回はModelsとします)を作成し、ダウンロードしたファイル"AliciaSolid.vrm"エクスプローラーからドラッグアンドドロップすると、プレファブができます。
13. できたプレファブをHierarchyウインドウのCharactersの下にドラッグアンドドロップします。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215278/bbfff27a-c0b7-77cc-c9fc-347ce46926ee.png)
14. CharactersのChange Character UIのTarget Charactersの設定値を2に変更し、Element1にAliciaSolidをドラッグアンドドロップします。同じようにCopy Character ComponentsのTarget Charactersの設定値を2に変更し、Element1にAliciaSolidをドラッグアンドドロップします。追加したいキャラクターがほかにもある場合は数字を増やして同じような手順で変更します。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215278/03b2826d-2cd7-b1ae-34b8-2df5933ea014.png)
15. ビルド設定からビルドします。

#キャラクターの切り替えについて
左手にパネルが２個表示され、左側パネルにキャラクターのリストが、右側パネルにキャラクターの情報を表示されます。キャラクターのリストからキャラクターを選択し、"Select"ボタンを押すとキャラクターが切り替わります。選択やボタンの押下は右手のポインタで対象を選択してAボタンで実行します。
![com.oculus.vrshell-20190908-223552_Trim_300x300_fps10.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215278/b41da9de-9a0f-03a4-f10c-cf99eef2a47b.gif)

#GitHubに置いたソースコードについて
Unity Technologiesさんから配布されているVR Samplesという無料アセットから、今回改造しているMazeに必要なファイルを抜粋し、私が変更を加えたファイルを追加したものになります。そのほかのアセット(Oculus IntegrationやVRM)は含めていません。
追加したファイルは、Assets\VRSampleScenes\Scripts\MazeにあるChangeCharacterUI.csとCopyCharacterComponents.csの2個のスクリプトです。CC0としますので好きなようにご使用ください。
ChangeCharacterUI.csは、キャラクターの情報を表示・選択するためのUIを構築するためのもので、CopyCharacterComponents.csは、VRMからインポートしたプレファブに必要な設定をコピーするためのものです。

#実装にあたりつまづいたところ
### Componentのコピー
追加したキャラクターのプレファブに対して、元となるキャラクターのプレファブからComponentをコピーすることで、設定の自動化を実現することを考えました。UnityEditorInternal名前空間にあるComponentUtilityというクラスがちょうど同じ機能だったので、当初、これを使用して実装してみたのですが、エディタ上で動作確認して実機向けにビルドしようとしたところでエラーとなってしまいました。該当するクラスはエディタ上(PC上)でのみ動作できるようで、結局、自分で該当する箇所のコードを書くことになったのですが、一応動作するようになるまでにかなり試行錯誤しました。リフレクションの処理について、[キャラクターモデルを差し替える時にコンポーネントの付け替えを自動化したい話]
(https://soysoftware.sakura.ne.jp/archives/1340) を参考にさせていただきました。

### UIについて
UIについてこれまであまり触っていなかったため、どこから手を付けようかと考えたのですが、Oculus Integrationに含まれているCanvasWithDebugというプレファブが扱いやすそうだったので、これをベースに作成することにしました。
最初につまづいたのが、あとから表示内容を変更するのにどうしたらよいかということだったのですが(そのようなメソッドがなかった)、要素を追加するときに、追加した要素に対応するcanvasの情報が返されるので、これを使えば表示内容を変更できることがわかりました。
次につまづいたのが、UIの表示位置を左手にするためにLeftControllerAnchorの下にCanvasWithDebugを配置しているのですが、実際に動かしてみると、全然関係ない位置に表示されてしまいました。これは、もともとUIの表示位置を目の前に更新する機能があったためで、今回はこの機能が邪魔になっているためコメントアウトすることで対処しました。