NVIDIA Flex for Unity を使ってみた

##概要

この記事は、[Unity #2 Advent Calendar](https://qiita.com/advent-calendar/2018/unity2) 18日目の記事です。
NVIDIA Flex for Unityを試しに少し触ってみたので、それについて簡単にまとめてみます。

##NVIDIA Flexとは

まず、[NVIDIA Flex](https://developer.nvidia.com/flex#)とは、流体・軟体・布等の動きをリアルタイムでシミュレーションするミドルウェアです。
https://developer.nvidia.com/flex#
<img src="https://qiita-image-store.s3.amazonaws.com/0/254028/17dead61-426e-8c3b-a217-11b746fd82d6.jpeg" width=30%>

そして、[NVIDIA FleX for Unity](https://assetstore.unity.com/packages/tools/physics/nvidia-flex-for-unity-1-0-beta-120425)は、NVIDIA FlexをUnityで動作させるプラグインです。
（2018/12/18現在、1.0ベータ版となっています）
https://assetstore.unity.com/packages/tools/physics/nvidia-flex-for-unity-1-0-beta-120425
<img src="https://qiita-image-store.s3.amazonaws.com/0/254028/58b0da06-da9c-fc95-da55-52fb234885e6.png" width=60%>

##NVIDIA Flexを使ってみる　

今回、NVIDIA Flex for Unityを使って、試しにこんなものを作ってみました。
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">NVIDIA Flex for Unityを試しに使って軟体と流体を表示。エッグマフィンやワッフルをふるふるに。 <a href="https://t.co/yeXP4PQBBQ">pic.twitter.com/yeXP4PQBBQ</a></p>&mdash;  <a href="https://twitter.com/tomoyuki710/status/1074878808757493760?ref_src=twsrc%5Etfw">2018年12月18日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

食べ物のモデルと水の流れを NVIDIA Flexで動かしています。
上記の動画を見てもらうと、ハンバーガーやワッフル等が軟体として動いているのがわかってもらえるかと思います。

食べ物のモデルはAssetStoreにあったものをダウンロードして使用させていただきました。
https://assetstore.unity.com/packages/3d/props/food/3d-bakery-object-17167
<img src="https://qiita-image-store.s3.amazonaws.com/0/254028/0cb6a7c1-e82e-1261-1529-df869104e74d.png" width=50%>

##ポリゴンモデルを軟体(ソフトボディ)として表示する

では、試しにFlexでポリゴンモデルを軟体として表示してみたいと思います。

AssetStoreから[NVIDIA Flex](https://developer.nvidia.com/flex#)をダウンロードしてインポートし、
食べ物のモデル([3D Bakery Object](https://assetstore.unity.com/packages/3d/props/food/3d-bakery-object-17167))をダウンロードしてインポートすると、プロジェクトは以下のようになります。
（これから作成するファイルの置き場として、プロジェクトに FlexBakeryという名前のフォルダを追加しています。）
![InitialProject.png](https://qiita-image-store.s3.amazonaws.com/0/254028/57d79d77-834f-5dcd-33fa-5a5c96924a24.png)

まず、Flexでシミュレーションを行うには、**Flex Container** というアセットが必要なのでこれを生成します。

Create > Flex > Flex Container
でコンテナを生成します。
![FlexContainer.png](https://qiita-image-store.s3.amazonaws.com/0/254028/e9580ca8-0ccc-5098-7f77-6e6a64cf846b.png)

※このコンテナにFlexのオブジェクトを登録することで、オブジェクト同士の動きのシミュレーションを行うことができます。[^1]

次に、ハンバーガーのモデルを軟体で出すことにします。

Create > Flex > Flex Soft Asset
で軟体のアセットを生成します。

アセットの名前は SoftAsset_Hamburgerとしておきます。
![SoftAsset_Hamburger.png](https://qiita-image-store.s3.amazonaws.com/0/254028/6ec3e801-996c-3de3-64e4-f8e0fe956255.png)

ハンバーガーのモデル(FBX)は以下のフォルダにあります。
ここでは、Scale Factorの値を0.05として大きさを調整しています。
![HamburgerModel_.png](https://qiita-image-store.s3.amazonaws.com/0/254028/b8ca9ea7-7e84-958d-0ae2-1d46b1e60735.png)

そして、SoftAsset_Hamburgerをインスペクタで見て **Boundary Mesh** のところに
ハンバーガーのFBXのメッシュ(FBXの１階層下にあるやつ)をドラッグ＆ドロップします。
すると、ポリゴンメッシュが、Flexでシミュレーションするための粒子で構成されたモデルに変換されて、インスペクタに表示されます。
![DragDrop2__.png](https://qiita-image-store.s3.amazonaws.com/0/254028/3b71f707-35ca-a737-1c1b-1358c07df009.png)

次に、ハンバーガーのモデルをシーンに出すために
Create > Create Empty でシーンに GameObjectを追加して（ここでは名前をHamburgerとしています）、
その GameObjectに Add Componentで **FlexSoftActor** コンポーネントを付加します。
そして、**Container** のところにコンテナのアセット(FlexContainer)を、**Soft Asset** のところにハンバーガーの軟体のアセット(SoftAsset_Hamburger)をそれぞれ指定します。
このとき、**DrawParticles** のチェックボックスをONにすると、粒子のモデルがシーン上に表示されます。
![FlexSoftActor_.png](https://qiita-image-store.s3.amazonaws.com/0/254028/6329dd39-cdc5-9eba-6e81-b7f8a63801ea.png)

ハンバーガーのポリゴンモデルを軟体として表示するために、
ハンバーガーの GameObjectに、更に **FlexSoftSkinning** と、**SkinnedMeshRenderer** コンポーネントを付加します。

**SkinnedMeshRender** コンポーネントの **Mesh** のところにハンバーガーのポリゴンメッシュを、
**Materials** のところにはハンバーガーのモデルのマテリアルを指定します。

（これでハンバーガーのポリゴンモデルが表示されるようになったので、**FlexSoftActor** コンポーネントの **Draw Particles** はOFFにします）
![Clipboard03_3.png](https://qiita-image-store.s3.amazonaws.com/0/254028/236a489f-19b7-72dd-f6f4-6ed6a6e809ce.png)

この状態で、Unityエディタで Playボタンをクリックして実行すると、ハンバーガーが床に落ちてぽよんと弾むのを見ることができます。

他の食べ物のモデルも同様の手順で追加してみます。
※ **Flex Container** は2つ以上作らずに、同じ1つの **Flex Container**をそれぞれの**FlexSoftActor**のインスペクタに指定するようにしてください。
![Clipboard05_.png](https://qiita-image-store.s3.amazonaws.com/0/254028/d85646d5-3eed-e423-7fbf-d2a068435f44.png)
ちなみに、**Flex Soft Asset** の **Cluster Stiffness**（剛性、変形しづらさの度合い）の値で、軟体の柔らかさを変えられるので、
食べ物のモデルの種類ごとに、このパラメーターを調整してみるとより良い見た目にすることができます。

## 流体の表示
蛇口から水が流れ出るような感じで、流体をシーンに出してみることにします。

まず流体の粒子の発生源を作ります。
Create > Flex > Flex Source Asset
でアセットを生成します。

その FlexSourceAssetをインスペクタで見て、**Surface Mesh** の右端の○ボタンをクリックして、粒子の発生源となるメッシュを選択します。
ここでは Quad 形状のメッシュを選択します。
![Clipboard09_2.png](https://qiita-image-store.s3.amazonaws.com/0/254028/674dcf76-3ac5-3f2b-5070-3806bbf95f4a.png)
そして、**Mesh Tesselation** の値で、粒子を発生させる点の数を増やすことができます。
**Max Particles** はこのメッシュから発生する粒子の最大数です。

ここでは、それぞれのパラメーターの値を（スケールの値も）シーンに合わせて適当に調節しています。
![Clipboard11_.png](https://qiita-image-store.s3.amazonaws.com/0/254028/8e62a1e3-7c6a-e110-4487-edecd7e5e93d.png)

シーンに GameObjectを追加して、**FlexSourceActor** コンポーネントと **FlexFuidRenderer** コンポーネントを付加します。
そして、Container のところに FlexContainerのアセットを、Soft Asset のところに FlexSourceAssetをそれぞれ指定します。
![Clipboard14_2.png](https://qiita-image-store.s3.amazonaws.com/0/254028/6c7f0f90-df1e-1806-a58e-9bf7097250ee.png)

**FlexSourceActor** コンポーネントの **Fluid** のチェックボックスをONにします。
このパラメーターをONにすることによって、粒子は流体として発生します。

その他に、**StartSpeed** は粒子の初速を、**LifeTime**は粒子が発生してから消えるまでの時間(秒)を表しています。
ここではそれぞれのパラメーターをシーンに合わせて調節しています。
![Clipboard15_.png](https://qiita-image-store.s3.amazonaws.com/0/254028/598bbcf2-5812-8aab-7df7-357f5580f506.png)

シーンに流体の発生源を置いたので、これをUnityエディタで実行すると、
この動画のように、軟体のモデルを流体で押し流す動きを作ることができました。
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr" <a href="https://t.co/yeXP4PQBBQ">pic.twitter.com/yeXP4PQBBQ</a></p>&mdash;  <a href="https://twitter.com/tomoyuki710/status/1074878808757493760?ref_src=twsrc%5Etfw">2018年12月18日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 最後に
今回 NVIDIA Flex for Unityを試しに少し使ってみて、軟体や流体の動きを簡単に表示することができて結構楽しかったです。
まだベータ版ということもあってか、処理はかなり重いのですが、そのあたりは今後のバージョンアップに期待したいと思います。

## 参考にした記事
https://www.youtube.com/watch?v=Fp1SMb3SWoo
https://www.youtube.com/watch?v=2IOXPnbHuvo
https://www.youtube.com/watch?v=VelIt1v0CAY
http://www.asset-sale.net/entry/NVIDIA_FleX_for_Unity_%281_0_BETA%29

[^1]: （注釈）Flexのコンテナは正確に言うと、Flexで位置計算を行うための粒子のコンテナです。Flexでは剛体・軟体・流体・布等全て粒子から成るモデルで構成されていて、シミュレーションは全て粒子の位置計算によって行われています。軟体の動きは、軟体を構成する粒子のモデルから、粒子の相互作用を計算してスキンメッシュの形状に反映しています。