Unity + VRoid + androidスマホでお手軽にVR観賞を試してみる

##はじめに

ただいま趣味でゲームを作成中なのですが、ゲームエンジンをどうするか、という選択肢で急遽Unityが浮上してきました。
Unityは前々から使ってみたくて色々と本を買ってたのですが、全然手付かずだったので、この機会にやるか！と。

で、ふと「そういえば、前に試しに何となく作ったVRoidのモデルがあったな。。」というの思い出しまして、
「折角だからVR化しちゃうか！」となったのが今回の経緯です。
まあ本来の目的から完全に脱線してますよね。悪い癖です。。
でも「自分で作った3DモデルをVRで動かしてみたい！」って思いません？（思いますよね？だから仕方ないのです！）

そんなこんなで色々なサイトの情報を見てみたところ、かなり簡単に作れそうな感じ。。
（ジャイロ機能ってこんな簡単に実装出来るのね。。）
ちなみに参考にさせて頂いたサイトは以下です。（本当にありがとうございます）

https://3owebcreate.com/web/design/vroid_studio_animetion
https://qiita.com/ELIXIR/items/084839ae0824985fcfaf

ちなみにVRっていうとOculusとかが有名ですが、自分にはなかなか手が出せない。。（お値段的に）
なので今回は簡単に試せるスマホのGoogle Cardboard用に作成してみたいと思います。
（勉強しながらって感じになるので、まぁ参考程度のモノと思っていただければ。。）
（画像を沢山張ってるので作業が多そうに見えますが、1時間もあれば終わる気がする。。）

##使うもの

1. VRoidのvrmファイル
2. unity
3. スマホ（あとCardboardも）

使うものはこれだけ（多分）ですが、SDK等のインストールが必要そうな感じです。
では、早速作っていきたいと思います。

##1. VRoidモデルの準備

今回は既にVRoidのvrmファイルが作成してある状態です。
が、モーションは全く作ってません（過去の自分はモデルを作って満足したらしい）

余談ですが、VRoidモデル自体はかなり簡単に作成出来た気がします（まぁ単に作り込んでないだけなのですが）
ただ、衣装の作り込みは割と面倒だったかも。。（衣装だけこだわった）
blenderで細かく作り込もうとして、予想以上に難しくて断念した記憶があります。。

下記がvroid studioから出力したvrmファイルです。（testちゃん）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/7617a443-69cd-97f3-4a2d-792499729ffc.png)

##2. Unityプロジェクト作成

まずは「Unity Hub」を起動し、プロジェクトを新規作成します。
ちなみに自分は「2019.3.15f1」のバージョンを使用してます。
プロジェクト名を「TEST_VR」にして、テンプレートに「3D」を選択、と。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/0e96543f-c78c-90a1-9ec2-674e59a6aac1.png)

「作成」を押すとUnityが立ち上がります。

##3. UniVRMパッケージをインポート

Unity 向けの VRM ファイルの読み書きを行う C# による標準実装、それがUniVRMとのこと。
UniVRMを使うことでVRM形式のファイルが簡単に編集できるという感じでしょうか。。
使わせて頂くしかないですね！

https://github.com/vrm-c/UniVRM/releases
上記リポジトリに公開されているので、最新のパッケージをダウンロードしてきます。
自分が作業した時点では「UniVRM-0.55.0_ce1c.unitypackage」になるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/fb52f3b1-ecfd-d9e0-a300-9996060971ae.png)

ダウンロードが完了したら、このファイルをダブルクリックします。（Unityは起動した状態で）
すると以下のウィンドウが立ち上がります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/84f46e98-77b0-98b6-4b3b-eed244a90c49.png)

インポートをクリックします。

インポートが完了し、プロジェクトアセット内にVRMというフォルダが出来ました！
（これで簡単にvrmが読み込めるはず。。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/239a11da-9b8d-d2d4-dece-174181eb149a.png)

##4. 3Dモデルのインポート/配置
きましたね。今回の山場と言っても過言ではない（いや、過言ですね）

インポート自体はUnityのAssetsにドラッグ＆ドロップするだけのようです。（なんて簡単なんだ。。）

これを。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/da3fdbaa-5f21-e2fe-e95b-16767112cd89.png)

こうすると。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/04e9bba0-78b1-d9e2-5d9d-640d78c60889.png)

お、確かにtestちゃんのプレハブが作成されてますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/25675216-b7e4-783a-08f0-74220d1a4309.png)

で、このプレハブをヒエラルキーのシーン内にドラッグ＆ドロップすると。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/cf78756a-a770-6a93-c9aa-66b9c0c85000.png)

おー！きました！ゲーム内になんかポツンと誰か表示されましたね！ひゃっほー！

##5. オブジェクトの調整とVR化
きましたね、メインイベントが。
Google CardboardでのVR化はSDKが公開されていて、ビルド時に適用するだけで簡単に作れるらしいのですが、それじゃ面白くないので「今回は手動でVR化」します。
ちなみに手動で設定した方が映像の描画が早いらしく、処理遅延をなくせるというメリットがある模様。
カスタマイズも好みで色々出来るので、手動の方がお得っぽいですね。

まず、モデルが後ろを向いてるのが気になりますね。。
モデルを選択してTransformの回転Yを180に設定してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/1e6940d5-085b-fd5f-cb78-f844cf8fa90b.png)

お、こっちを向きましたね。
ヒエラルキーで「空のオブジェクトを作成」を押し、オブジェクト名を「Camera」にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/38ac0a95-5051-d95e-c322-3b6abb586425.png)



次にヒエラルキーでMainCameraを選択して、cameraの中にドラッグ＆ドロップします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/2cb00bb4-7e17-253b-a718-265113dcb2b5.png)


ふむ、中にMainCameraが入りました。
次にMainCameraを「Main Camera L」にリネームするようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/261634df-5dc7-cde3-9bb8-58b03edc23ac.png)

OKですね。次に「Main Camera L」を複製します。
「Main Camera L」を選択→右クリック→複製です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/c2b0b80c-b48b-8483-78c6-ec7a2d788cd2.png)

複製した「Main Camera L (1)」を「Main Camera R」にリネームします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/adaf2ce0-590b-d19c-8c7c-8133b7841cc0.png)

次にMainCameraRを選択し、インスペクターからTagを「Untagged」にします。
このタグというのはその名の通り、参照ラベルみたいですね。
複数のゲームオブジェクトをまとめて扱いたいときに同じタグを設定する、グループ化みたいなイメージ？
ふむ、勉強になりますな。ちなみに「Untagged」はタグなしです。mainCameraから分離するってことかな？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/45812557-9797-a1fb-1853-26471e0280be.png)

次にMainCameraRのインスペクターから「Audio Listener」を消します。
右クリック→コンポーネントを削除ですね。
「Audio Listener」というのは音声を再生するデバイスとして機能するようです。
MainCameraにくっついているのがデフォルトみたいですが、シーン内で機能するのは一つだけのようなので、こいつは要らないってことですね！
（まあ今回、音声なんてありませんが。。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/caedbbe9-6814-28a5-4f9a-857ec5019ff0.png)

現在、2つのカメラは完全に重なっている状態だと思うので、調整していきます。
まずは「Main Camera L」です。ビューポート矩形を以下にします。
X=0 Y=0 w=0.5 h=1
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/cd4fa7da-cb65-e605-daaa-4ed0c8a98bc8.png)


次に「Main Camera R」です。ビューポート矩形を以下にします。
X=O.5 Y=0 w=0.5 h=1
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/0c3e8ebc-a09e-5417-0196-f3121ca070ec.png)

なんとなくVR感が出てきましたね。
ビューポート矩形というのは、カメラの映像を画面上のどこに表示するかの設定みたいですね。（設定値は0~1）
いまは2つのカメラの映像を並べて表示してるイメージだと思われます。

次にカメラのTransformを調整していきます。

まずは「Main Camera L」のTransformを以下に設定します。
位置：X=-O.1(-0.1) Y=1 Z=-2.5
回転：X=O Y=0.1(+0.1) Z=0
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/9547a6eb-3cdd-0adc-89e5-7fdac904553a.png)

次に「Main Camera R」です。
位置：X=O.1(+0.1) Y=1 Z=-2.5
回転：X=O Y=-0.1(-0.1) Z=0
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/2a03b713-b66e-48be-081a-d8f7b4321e15.png)

これでカメラの位置調整は完了です。
(モデルがあまりに小さいからカメラを近づけたけど、その分調整した方が良いのだろうか。。一回見てからだなぁ)

##6. ジャイロ設定

という訳でジャイロ機能を付けます。
プロジェクト→作成→C#スクリプトを選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/549bff90-31a3-3ef7-9bf0-709fc5fc9385.png)

ファイル名を「gyro」にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/3031ab65-665e-23ac-8c31-8dac9cd3f5a7.png)

作成した「gyro」をダブルクリックすると、エディターが起動してきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/9d0bddfe-8179-5adf-cf94-5d48786abad2.png)

ここから中身を追加していきます。
Startメソッドに以下を追加します。

```CS
Input.gyro.enabled = true;
```
ジャイロセンサによる入力を有効にするという意味っぽいですね（見た感じ）

続いてUpdateメソッドに以下を追加します。

```CS
transform.rotation = Quaternion.AngleAxis(90.0f, Vector3.right) * Input.gyro.attitude * Quaternion.AngleAxis(180.0f, Vector3.forward);
```
ジャイロセンサから取得した値を、直接カメラの角度に適用しているみたいですが、、
なにこのQuaternionってやつ、めっちゃ難しいぞ。。（数学詳しくないと理解できない。。）
とりあえず、、Quaternion.AngleAxisは「AngleAxisはaxis（軸）の周りをangle度回転するQuaternionを生成します。」って意味のようです。第1引数で角度（オイラー角）、第2引数で軸を指定しているとのこと。なお軸は以下。

Vector3.right（x軸を指定したい場合）
Vector3.up（y軸を指定したい場合）
Vector3.forward（z軸を指定したい場合）

頭が痛くなってきたので、考えのはここまでかな。。
ようはジャイロセンサーの入力値をカメラの上下左右角度に加算しているってことなのだろう。。

とういうわけで、結果的にgyroの中身は以下になります。

```cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class gyro : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Input.gyro.enabled = true;
    }

    // Update is called once per frame
    void Update()
    {
        transform.rotation = Quaternion.AngleAxis(90.0f, Vector3.right) * Input.gyro.attitude * Quaternion.AngleAxis(180.0f, Vector3.forward);
    }
}

```

これでスクリプトは完成なので、cameraオブジェクトのコンポーネントとして追加します。
（gyroファイルをヒエラルキーのcameraオブジェクトにドラッグ＆ドロップすればOKです）
以下みたいになってれば〇。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/e34348bc-82c6-51e5-135b-c5102ea561c5.png)

##7. モーション設定
さて、作業も終盤です。
ここまでの作業でVR鑑賞の機能としては完成なのですが、重大な問題があります。
それは「モデルが色々動いてくれなきゃ鑑賞にならないやん」です。

ただ前述のとおり、モーションは全く作成しておりません！
（正直、この検証のためにわざわざ作る気力はありません。。）

という訳で今回は、ユニティちゃんのモーションを使わせて頂こうと思います。
まずはウィンドウメニューから「アセットストア」を開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/45e1f48a-b170-7731-52e1-893ac5d2b8cb.png)

検索BOXに「unity-chan」と入れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/166a2098-7647-89a6-8f23-3a168756bf47.png)

検索結果に出てくる「unity-chan! Mosel」をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/18bd344a-5059-f41d-8f7c-bce72630dd74.png)

本当はダウンロード→インポートの順番なのですが、自分は既にダウンロード済みなので、インポートします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/ad9a0761-e8bd-0a18-3ba6-ddf9e5d1d7be.png)

ポップアップが出てくるので、インポート！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/c524f1d2-7ea6-97d1-affb-576cf19877f3.png)

（勢いで全部インストールしちゃったけど、正直モーションだけで良かった。。）

これでユニティちゃんモデルがインポートされました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/29d079f1-3f2b-7573-f102-5a05f51d48e8.png)

ユニティちゃんフォルダの　Unity-chan! > Unity-chan! Model > Art > Animations のフォルダをアセット直下に持ってきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/648c3e8b-1d4c-2842-04bf-a9aeffb7fb30.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/ab510f73-e442-76aa-4abf-2f6d6cf2c442.png)

これでユニティちゃんの役目は終わったのでフォルダごと消します（ありがとうユニティちゃん。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/3e8cb37f-9cd7-abd8-5b20-f56954d538b6.png)

次にヒエラルキーでtestちゃんを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/cb376402-a8b9-5e5a-ca86-de85db671a58.png)

インスペクターからAnimatorを探し、「コントローラー」のインプットボックスをクリックします。
コントローラの選択が出てくるので、「UnityChanActionCheck」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/d2718c73-5e66-2091-9660-c7353314de8b.png)

次にウィンドウからアニメーターを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/d2a13bbb-5425-3133-4f89-b8ea5e4c9a79.png)

いっぱいモーションがありますね。
自動で全部のモーションが流れるようにしたいので、オレンジのモーションで右クリックして「遷移を作成」を選択、遷移したいモーションに繋ぎます。（もっと良いやり方がありそうだけど。。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/4858523a-9175-5732-ca56-7d545d66fc43.png)

これで自動で色々なモーションをしてくれるようになりました！

##8. ビルド
遂にビルドする時がやってきました。。
ただ、ビルドをする前に次のモノを準備する必要があるようです。

・AndroidSDK
・JDK（1.8まで）

上記の2つは以下のサイトで「AndroidStudio」をインストールすると一緒に入手出来るようです。

https://developer.android.com/studio/index.html

今回インストールしたバージョンは3.6みたいです。
ちなみにインストールしたら一回起動して下さい。初回起動時にSDKがインストールされるらしいです。
終わったらもう「AndroidStudio」は使わないので閉じちゃいましょう。

そしたらUnityに戻って、編集→環境設定を開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/6746aee1-8606-7e89-6c46-10f19116137e.png)

外部ツールの下の方に、JDKとSDKのパスを指定する欄があるので、それぞれのパスを指定します。
（JDKを探すのに凄く手間取りました。。）
ちなみに自分はDドライブにインストールしてるのでDですが、普通はCになると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/005c27a8-0f09-ffe4-4f57-6a3c05b2f19c.png)

これで準備は終わりなので、ファイル→ビルド設定を開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/9b881495-ba84-60f7-1e38-a80f1a6f6125.png)

プラットフォームにandroidを選択して「Switch Platform」をクリックします。
Android build suportが未インストールの場合は、入れちゃって下さい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/87055b3c-ee0a-2e34-ccb4-9d8ad3ec1c3d.png)

デフォルトの状態ではシーンが何も含まれていないので、「シーンを追加」を押して、作成したシーンをビルドに含めます。
そしてビルドを押しちゃいます！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/7acc44d7-1bfe-c10c-3cb0-b9c9782cad7e.png)

任意のフォルダを選択して、保存を押します！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/078d5092-5157-dde8-0d4a-e2b207edfc8b.png)

しばらく待つと、.apkファイルが出力されます。これでビルドは完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/17a62d49-49ce-d653-8fa3-c7b588d1e73c.png)

##7. アプリインストール、実行
あとはapkファイルをスマホに移してインストールすれば完了です。
方法は何でも良いと思いますが、今回はGoogleDrive経由で持っていきます。
（PCからGoogleDriveにアップして、スマホからダウンロードするだけです。）

機種によるかもしれませんが、スマホでダウンロードが完了すると、インストールするか尋ねてきます。
（ちなみに「開発元不明のアプリ」のインストールを許可しておく必要があります。インストールが終わったら設定を戻しておきましょう）

起動するとこんな感じになってると思います。
ちょっと感動ですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/8eb42c2f-1346-3e91-311b-4ddb19553512.png)

##おわり
というわけで今回はスマホVRを試してみました。
内容自体はそんなに難しくないですし、初歩的なモノではありますが、
やっぱり自分で作ったキャラが3Dで自由に動いてくれると、めっちゃ嬉しいですね！
あー、Oculus買っちゃおうかなー、、