UnityでVRゲームのプロトタイピングをしてみた

# 金が欲しい
**なんか一億円くらい遊ぶ金が欲しいので、今流行りのVRのゲームとか作って大儲けしたい！**
って吠えてたら「まずはプロトタイピングしてブツを見せてみなさい」って言われたので作りました。この記事はその過程です。

### ステージ
[Pack Gesta Furniture #1](https://assetstore.unity.com/packages/3d/props/furniture/pack-gesta-furniture-1-28237)
![d9342776-d237-4f2c-ac7f-f8652e036ee7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146245/8d3a6b88-865f-1ce2-6fba-f48aa76973a0.jpeg)

VRならLowPolyな環境が大半ですが、今回作りたかったものはリアルなやつなので、リアルな部屋で無料のやつ。
リアルっぽいのほしいなーってときはいつもこれを使ってます。

![スクリーンショット 2019-04-21 13.05.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146245/96d8e092-cab2-d68e-8c03-fa93300dc200.png)
こういう屋内のシーンの場合、後から室内を調整することもあるので、壁や天井をこのようにまとめておくと一気に`disable`して室内を見やすくできるのでよいです。
![スクリーンショット 2019-04-21 13.11.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146245/45e323bf-b42c-aad6-62b1-26ec45ebb087.png)
でなんかまるごとMeshColliderつけておきます。

### キャラ
[Bodyguards](https://assetstore.unity.com/packages/3d/characters/humanoids/bodyguards-31711)
![0bdd1f9a-132b-47e0-aebb-16a1ae4a0ae2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146245/a535e8ac-58ca-f8f8-14e1-24500b57bf14.jpeg)
VRなので自キャラとかはいらないですが他のキャラは必要です。
今回は*無料で*一番リアルっぽいこれを選びます。

[Idle MoCap](https://assetstore.unity.com/packages/3d/animations/idle-mocap-28345)
![86f37447-0dff-460c-8204-eacf944a8658.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146245/2bb82970-af4a-7a92-048e-f503a8be8bfb.jpeg)
ぼんやり立っててくれてるだけでいいので、アニメーションはこれ。

実はAssetStoreでアニメーションを探すのってけっこう手間です。見本がYoutubeなので、見てるだけでも時間がかかります。
UnityでAnimationを必要とするような開発してる人はAdobe CC契約してると思うので[mixamo](https://www.mixamo.com/#/)で探したほうが楽かも。ここのAnimationライブラリはかなり充実している上に、検索も簡単だしプレビューもさっと見られるので時間が節約できます。

### 死んだらぐにゃぐにゃなるやつ
[Ragdoll](https://docs.unity3d.com/ja/current/Manual/wizard-RagdollWizard.html)のことです。
この単語をなかなか思い出せなくて、検索履歴が「Unity　死体」「Unity 死ぬ」「Unity 死んだら」とかになってました。
でUnity標準のウィザードがこんな感じです。
![スクリーンショット 2019-04-21 13.42.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146245/2801f2db-90c5-bfc4-33d3-858648ff8875.png)
**んなめんどくせえことぜってぇやんねぇからな！**

でまあ調べたら[いい感じにやってくれるやつ](http://www.asset-sale.net/entry/Ragdoll_helper)あるのでそれを使います。
[Ragdoll helper](https://assetstore.unity.com/packages/tools/modeling/ragdoll-helper-49288)
![922cfe01-71aa-4509-81b9-c60e83af0e18.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146245/45273367-cc03-aacc-b3fd-173299cc4a8a.jpeg)

`Ragdoll`を設定していても`Animator`の動きが優先されます。なので死んだときに`Animator`を`disable`すれば死体になりますが、それだと裏で結局`Ragdoll`分の`Collider`が計算されている気がするので、通常時は`Ragdoll`用の`Collider`は`disable`にしておいて死んだときに全部`enable`にする……とかしたほうがいいんじゃないでしょうか。

### 操作
まあ**金が欲しい**と吠えているくらいですからVR機材とか持ってないわけですが、基本的にDayDreamやOculusなどVR系のPrefabはこんな構成です。
![スクリーンショット 2019-04-21 14.29.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146245/be81ca1a-a908-dcff-029a-010939601e30.png)

でバットが欲しいので素材を探してきます。

[Small Survival Pack](https://assetstore.unity.com/packages/3d/props/small-survival-pack-20565)
![32b0cf58-4f55-4861-a769-5fbc23a45ace.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146245/e150f30d-5fb1-0d03-5717-6cf075c02525.jpeg)
あらかじめバットの形状に合わせて`Collider`が調整してあっていい感じ。
このバットを先程の`Right`の子オブジェクトとして配置します。こうすることでコントローラの動きに連動してバットが動くようになります。
衝突判定をつけるために`RigidBody`を付与します。このとき`Constrains`にすべてチェックを入れておかないと、バットがなにかに衝突したときに反動を受けてCameraのPrefab全体が回転してVR酔いが大変なことになります。ぜひ試してみてください。
![スクリーンショット 2019-04-21 14.38.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146245/34351a55-f5ed-3746-bbcd-12bfee5e79d5.png)

VR機材は持ってないですがNintendo Switchは持ってます。SwitchのコントローラであるJoyconは3DOFです。BluetoothでペアリングすればUnityの入力装置として使えます。

[【Unity】Nintendo Switch の Joy-Con のジャイロ・加速度・傾きの値を取得したり、振動させたりすることができる「JoyconLib」紹介](http://baba-s.hatenablog.com/entry/2017/11/12/090000)

[JoyconLib](https://github.com/Looking-Glass/JoyconLib)

自分のPCはmacですがとりあえずクローンしたもの一式つっこんだら動きました。エラーは出てましたがログ出力する箇所だったのでコメントアウトしただけ。

移動法の参考記事。transform.rightを使う発想がなかった。
[Unityでカメラの向きを基準に移動する方法と、追従して回転できるカメラの実装](https://tech.pjin.jp/blog/2016/11/04/unity_skill_5/)

で参考記事のスクリプトをコピペしつつ「左スティックで移動、右スティックで視点操作」できるようにします。

```c#
// Updateの中

var r_stickForce = m_joyconR.GetStick();
var l_stickForce = m_joyconL.GetStick();

// _camera = カメラPrefabのRootObject
var currentPosition = _camera.position;
var forward = _camera.forward;
forward.y = 0;
var right = _camera.right;
right.y = 0;

currentPosition += forward * l_stickForce[1] * 0.1f;
currentPosition += right * l_stickForce[0] * 0.1f;

var currentRotation = _camera.eulerAngles;
currentRotation.x += r_stickForce[1];
currentRotation.y += r_stickForce[0];

_camera.SetPositionAndRotation(currentPosition, Quaternion.Euler(currentRotation));

// _right = バットのTransform
// JoyconとUnityの角度の表し方がは違うらしいがこれで縦持ちでしっくり来る
var q = m_joyconR.GetVector().eulerAngles;
_right.rotation = Quaternion.Euler(-q.y, q.z, q.x);
```


次はキャラの方です。別のクラス作るのめんどくさいのでUniRxで`Collider`の判定をします。

```c#
// _rightCollider = バットのCollider
_rightCollider.OnCollisionEnterAsObservable().TakeUntilDestroy(this).Subscribe(
    (collision =>
    {
        if (!string.Equals(collision.gameObject.tag, "GameController"))
        {
            // 家具に当たったときの判定がめんどくさいのでキャラのパーツすべてにGameControllerのタグを付ける
            return;
        }

        // キャラのAnimatorをdisable。本来ならcollision.gameObjectからどうにかして引っこ抜く。
        _animator.enabled = false;
        // そのComponentがないときにGetComponentするとnullが返ってくるのでその場合はAddComponentする。        
        // トリッキーなコードなので使ったらだめ。
        var rigid = collision.gameObject.GetComponent<Rigidbody>() ?? collision.gameObject.AddComponent<Rigidbody>();
        rigid.AddForce(m_joyconR.GetAccel().normalized * 20f, ForceMode.Impulse);
        m_joyconR.SetRumble( 160, 320, 0.6f, 200 );

    })
);
```

以上で完成しました！　さっそくプレイしてみましょう。


### プレイ

![ezgif-1-1b8f1dbd80e8.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146245/f4e0100c-ae3d-5fd2-47b8-1b53053af66e.gif)

## コンセプト
VRは疑似体験に最適。トレーニングツールなどにも導入されている。
今回は3DOFだったが、6DOFのコントローラを使って振動なども調整すればリアルな「人を殴り殺す感触」を体験できる。
殺す人数は少数。多すぎるとゲーム性が強くて実感が薄れる。
みんなゾンビとかいっぱい殺してるけど人間が殺したくてしょうがない奴もいるはず。

## 反応
- 10分くらいで飽きる奴
- 売ったら逮捕されそう

## 感想
だいたい3時間くらいでプロトタイピングできたので、改めてUnityはすごいなって思いました。
あと、実際作って操作してみたらあまりにもやばいかったのでいずれ規制されそうだなって思いました。

おしまい。