Unityでの衝突テスト

#目的  
Unity内で複雑形状のモデルが、それなりに正しく衝突し、衝突した際の外力影響を受けるようにする

#環境
・OS　Ubuntu 18.04.05
・Unity  2020.2.3f1 Personal

#適当なやり方の推定
Unity内でのモデルの干渉設定はゲーム系を対象にしているからか、Box等の簡易モデルで表現をしがち。
理想は、モデルファイルの外形をそのまま、干渉モデルとする。

この干渉モデルに対して物理演算を有効にすることで、目的を達成する。

#干渉モデル設定
干渉モデルはUnityではColliderで設定される。
https://docs.unity3d.com/ja/2020.3/Manual/CollidersOverview.html

> コライダー
Collider (コライダー) コンポーネントは、物理衝突のためのゲームオブジェクトの形状を定義します。コライダーは目に見えないので、オブジェクトのメッシュと正確に同じ形状にする必要はありません。実際、メッシュを大ざっぱにあわせた方がゲームではより効率が良く、違いもわかりません。

上記の説明を読むと、簡易モデルで表現するのがオススメとあるが、モデルに沿った形で衝突をさせたいためMeshColliderを使用する。

> メッシュコライダー
ただし、複合コライダーでさえ十分に正確でない場合があります。3D では、Mesh Colliders (メッシュコライダー) を使用すると、ゲームオブジェクトのメッシュの形状に正確に一致させることができます。2D では、Polygon Collider 2D (2D ポリゴンコライダー) はスプライトグラフィックスの形状と完全には一致しませんが、形状を任意の LOD に調整できます。  
これらのコライダーはプリミティブタイプよりもはるかにプロセッサーに負荷をかけるため、良好なパフォーマンスを維持するために慎重に使用してください。また、メッシュコライダーを別のメッシュコライダーと衝突させることはできません (つまり、接触させても何も起こりません)。Inspector でメッシュコライダーの Convex (凸状にする) にチェックすることで、これを回避できる場合があります。これにより、コライダーの形状を “凸包” に生成します。これは、元のメッシュに似ていますが、くぼみが埋められています。  
この利点は、凸状メッシュコライダーは他のメッシュコライダーと衝突可能であるため、適切な形状の動くキャラクターにこの機能を使用できることです。ただし、推奨する使用法は、シーンのジオメトリにメッシュコライダーを使用し、移動するゲームオブジェクトの形状を複合プリミティブコライダーを使用して近似することです。

ただ、注意点として上記に記載あるように、ColliderをConvexに設定しないとMeshCollider同士の衝突ができない。

## テスト環境

衝突のテストして以下のモデルを使用した。

・Plane
　特に意味はない。
　落下した際に地面と衝突等しないかと期待して追加。
　「右クリック」→「3D Object」→「Plane」で追加する。
![Screenshot from 2021-06-16 23-59-59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689420/3188233d-9a49-21c3-b8f4-d62215098d6b.png)
・Cube
　自由落下させ、目的の複雑形状モデルに衝突させるために追加。
　デフォルトのままだと、落下しないしないため、RigidBodyを追加し、物理演算を有効にする。
![Screenshot from 2021-06-17 00-03-26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689420/4bc3929b-8788-90eb-d828-4173da1982a9.png)
![Videotogif (3).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689420/31f687ec-eebd-5907-3ba8-9c796ccf40b7.gif)

・テント
　複雑形状モデルとしてテントのモデルを使用した。曲線があったり、くり貫かれている箇所があったりと、テストとして十分なモデルであったため。
　https://free3d.com/3d-model/green-mesh-tent-v1--54743.html
　「Assetes」に追加し、対象のObjファイルをD＆DでSceneに追加する。
　このままだとサイズ感が合わないため、Scaleをすべて「0.01」に設定する
![Screenshot from 2021-06-17 00-11-36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689420/15702cb9-a050-49a2-e61f-249ed9fbd6bc.png)

# RigidBodyについて
　https://docs.unity3d.com/ja/2020.3/Manual/class-Rigidbody.html
　Objectに対して物理特性を追加することができる。
　RigidBodyがないと、重力の影響を受けないし、衝突した際に飛ばされたりもしない。

　（例1）
　上のCube：RigidBodyあり。Use Gravityは有効
　下のCube：RigidBodyなし。
　![Videotogif (4).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689420/b98976c6-03e0-ae69-349a-fafe56e37ea9.gif)

　上のCubeが衝突しても、下のCubeは動かない。

　（例2）
　上のCube：RigidBodyあり。Use Gravityは有効
　下のCube：RigidBodyあり。Use Gravityは無効
　![Videotogif (5).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689420/79badd5e-effa-b362-265c-9e6e2bdf2361.gif)

　上のCubeが衝突すると、下のCubeは飛ばされる。
　
## Is kinematic
　RigidBodyにはIs Kinematicという設定がある。
![Screenshot from 2021-06-17 00-20-45_kinematic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689420/b1d782a7-3bf9-5f25-9152-ed73e72e3211.png)
 これを有効にすると、運動学が有効になる代わりに、物理演算が無効になる。自前で運動学を解く方程式を書いてTransformを変更する際に、有効にするのだと思う。
　今回、気をつける点としては、「Is Kinematic」を有効にすると、自由落下もしないし、他の物体と衝突しても飛ばされなくなるため、目的を達成できなくなる。
　
　（例3）
　上のCube：RigidBodyあり。Use Gravityは有効
　下のCube：RigidBodyあり。Use Gravityは無効　Is Kinematicは有効
![Videotogif (6).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689420/0d930df6-ee81-0d37-04de-5deffca88d09.gif)

　（例1）と同じ挙動を示す。


## MeshColliderを用いた干渉モデル設定
　こっからが本題となる。
　テントを天地逆転に配置し、その情報にCubeを配置する。
　ここから、Cubeを自由落下させる。"Cubeがテントの内に入り"つつ、"テントが移動"したら、目的を達成できたと言える。

![Screenshot from 2021-06-17 00-32-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689420/8e23b674-bec7-3fa5-3c61-35fbcd9ed16a.png)

### テスト1　MeshColliderを追加
　テントの全要素に「MeshCollider」を追加する。設定はデフォルトのままなので、「Convex」は無効とする。
　・Cubeがテント内に入る→OK
　・テントが移動→NG
　![Videotogif (8).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689420/d59b8dc8-6ebb-a88c-0bdd-7f2e7d85ebd6.gif)

　干渉モデルはモデルの外形通り設定されているため、テント内にCubeが入ったが、テントの運動学が設定されていないため、テントは移動せず。

### テスト2　RigidBodyを追加
　テスト１の結果から、テントが移動しない原因がRigidBodyが設定されていないことが判明するため、RigidBodyを追加する。
　テントは自由落下してほしくないため、Use Gravityは無効にする。
　・Cubeがテント内に入る→NG
　・テントが移動→NG
![Videotogif (9).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689420/b4e630bb-cda0-d6a0-6770-5fc30719d398.gif)

　Cubeとテントが衝突してくれなかった。
　また、以下のエラーが発生している。
　Unity5以降はConvexでないMeshColliderは、Kinematicを設定しないといけない。
　ConvexでないMeshColliderを使用する場合は、Kinematicを有効にするか、RigidBodyを使用するなと。
> 　Non-convex MeshCollider with non-kinematic Rigidbody is no longer supported since Unity 5.
If you want to use a non-convex mesh either make the Rigidbody kinematic or remove the Rigidbody component. Scene hierarchy path

### テスト3　Kinematicを有効
上記のエラーで言われたように、Kinematicを有効にする。

　・Cubeがテント内に入る→OK
　・テントが移動→NG
（GIF省略）

結果はテスト1と同じ。
衝突はするが、物理演算がされないためテントは移動しない。

### テスト4　Kinematicは無効　Convexは有効
　テスト3はKinematicを有効にしたが、今度はConvexを有効にする。
  また、テントの要素同士が再生後に即衝突し、Cubeが落下する前に、テントが吹き飛んでしまったため、テントのOpacity要素は無効化した。
　・Cubeがテント内に入る→NG
　・テントが移動→OK
![Videotogif (10).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689420/d0e76d29-9cb8-e1cb-3e5b-796930d76b39.gif)


　Convexを有効にしたため、干渉モデルがモデルファイルと異なってしまう。
https://docs.unity3d.com/ja/2020.3/Manual/class-MeshCollider.html
　凸状に補正させれた結果、テント内にCubeが入り込めなくなってしまった。


# まとめ
複雑形状を干渉対象にする→MeshColliderを使用する。

MeshColliderで干渉をさせる_1→Convexを有効にしないといけない→複雑形状でなくなってしまう。
MeshColliderで干渉をさせる_2→IsKinematicを有効にしないといけない→物理演算がされない。

目的を達成できない