[Unity] ParticleSystemでMeshを描画してバナー等の背景に使うといい感じになる

![banner.png](https://qiita-image-store.s3.amazonaws.com/0/102664/e1b424af-0abc-de9f-acb1-f9cca091b8f6.png)

これってトリビアになりませんか？ (なりません)

# 実行環境
* Unity2018.2.7f1

# 概要
最近、UnityのParticleSystemでMeshを描画するのにハマっています。
幾何学的な絵を作り、それをIllustratorでサイズ等を加工し、バナー等の背景に利用しています。
Unityで絵作りをしてそれを静的コンテンツに持ってくる手法は非常に楽で良いです。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="und" dir="ltr"><a href="https://t.co/6sAxyoNbxe">pic.twitter.com/6sAxyoNbxe</a></p>&mdash; 青木とと\(ˊᗜˋ*)ﾉ (@lycoris102) <a href="https://twitter.com/lycoris102/status/1041301310702706688?ref_src=twsrc%5Etfw">2018年9月16日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">はぁ…楽しい... <a href="https://t.co/Qxp1M2JDjH">pic.twitter.com/Qxp1M2JDjH</a></p>&mdash; 青木とと\(ˊᗜˋ*)ﾉ (@lycoris102) <a href="https://twitter.com/lycoris102/status/1047284285676212224?ref_src=twsrc%5Etfw">2018年10月3日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">前回の Gotanda.unity の動画、許可を頂いたものから随時公開しております！<a href="https://t.co/jGBJx9Lqet">https://t.co/jGBJx9Lqet</a> <a href="https://t.co/YSBTV8DDom">pic.twitter.com/YSBTV8DDom</a></p>&mdash; 青木とと\(ˊᗜˋ*)ﾉ (@lycoris102) <a href="https://twitter.com/lycoris102/status/1048217509889957889?ref_src=twsrc%5Etfw">2018年10月5日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ParticleSystemでMeshを描画する手法は既に各所で纏められていますが、備忘録として置いておきます。

# ParticleSystemにてMeshを描画する
まずはScene上に `ParticleSystem` を追加します。

![particle_mesh1.gif](https://qiita-image-store.s3.amazonaws.com/0/102664/ef7ac5fc-918f-f7ca-6a43-11d4bbb26c2f.gif)

次に `Renderer` Moduleを選択し、RenderModelを `Mesh` に変更します。
そして `Mesh` の項目から描画したい `Mesh` を選択します。今回は `Cube` を選択します。

![particle_mesh2.gif](https://qiita-image-store.s3.amazonaws.com/0/102664/2a680270-ba43-1731-35b5-c5fdb2cb8fa1.gif)

次に `Material` の項目を設定し、見た目を整えていきます。
`Material` を新しく作っていきます。`Shader` はParticle用のものを選択します。
 Unity2018から は `Particle/Standard Surface` および `Particle/Standard Unlit` が標準になっていくのでそちらを指定します。
(ただしモバイル端末で使用する場合は引き続き `Mobile/Particle/*` を使用していくのが良いでしょう)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/102664/5244d0f4-1b56-f45a-bccf-e48a772e0f00.png)
[【CEDEC2018】 パーティクル新機能の紹介 - YouTube](https://www.youtube.com/watch?time_continue=87&v=k2dF_9G1-3w)より

`Standard Surface` は光源の影響を受け、影の付き方等を考慮してくれます。

![particle_mesh3.gif](https://qiita-image-store.s3.amazonaws.com/0/102664/140f0256-2674-370e-48a9-804f4d20d6da.gif)

`Standard Unlit`は光源の影響を無視し、指定した色やテクスチャをそのまま出力します。

![particle_mesh4.gif](https://qiita-image-store.s3.amazonaws.com/0/102664/5bcbb584-baa4-5448-467a-45ba1ee898bd.gif)

# パラメータを調整する

`ParticleSystem` における各Moduleの説明はここでは割愛しますが、とりあえず色々なパラメータを触ってみることを推奨します。
1つオススメしたい機能としては `Random Between Tow Constants` というものがあります。
標準だと各パラメータに1つの固定値しか指定できないですが、上記の設定をすることで「2値の間でランダムに値を決定する」ということができます。
今回に限らず、演出を自然に見せたい時にオススメです。

![particle_mesh5.gif](https://qiita-image-store.s3.amazonaws.com/0/102664/e865d6c0-c1a1-7cce-8286-15d0998ee8a3.gif)

`Emission` Moduleで出力する数を増やしたり (`MaxParticles` で指定した数以上には出力されないので注意)
`Start Speed` ではなく `Velocity over Lifetime` Moduleで速度を付けたり
`Rotation over Lifetime` Moduleでそれぞれを回転させたり
カメラの位置を変更したり...

![particle_mesh6.gif](https://qiita-image-store.s3.amazonaws.com/0/102664/88ffc90e-e80f-a0a1-f27d-89b86a7d80a0.gif)

パラメータを調整するとこんな感じのものもノーコディングで作ることが出来ます。

# Mesh GPU Instancing を有効にする

Unity2018.1からMeshのParticleに対して `GPU Instancing` を設定できるようになりました。
標準の `ParticleSystem` ではCPU側でMeshを纏めて(バッチングして)からGPUに渡すことで、DrawCallを減らして負荷が増えないようにしています。
しかし、CPU側のバッチング処理はMeshのポリゴン数が多いとそれだけ負荷になるため、あまり多量のモデルを表示することが出来ません。

<img width="1006" alt="Unity 2018.2.7f1 Personal (64bit) - [PREVIEW PACKAGES IN USE] - SampleScene.unity - UnityParticleMesh - PC, Mac &amp; Linux Standal… 2018-10-06 14-22-05.png" src="https://qiita-image-store.s3.amazonaws.com/0/102664/7a3ca274-0825-f28d-2e79-c67d3af1af56.png">

`GPU Instancing`を有効にしないと、上記のようなWarningが出て、表示数が制限されることが確認できました。
`GPU Instancing`を有効にすることで、同一のMeshを複数、パフォーマンス良く描画することが可能になります (結果として多くのパーティクルを描画できます)

![particle_mesh7.gif](https://qiita-image-store.s3.amazonaws.com/0/102664/cdba14c9-bc20-47e8-fe07-ca4ef4fdb599.gif)

仕組みの詳細に関してはテラシュールブログさん/公式ドキュメントをご参照ください。

* [GPU インスタンシング - Unity マニュアル](https://docs.unity3d.com/ja/cur<img width="944" alt="Unity 2018.2.7f1 Personal (64bit) - [PREVIEW PACKAGES IN USE] - SampleScene.unity - UnityParticleMesh - PC, Mac &amp; Linux Standal… 2018-10-06 14-48-49.png" src="https://qiita-image-store.s3.amazonaws.com/0/102664/8e3ff4b6-0d37-6767-a2d5-db790cf1c229.png">
r![particle_mesh7.gif](https://qiita-image-store.s3.amazonaws.com/0/102664/d571dde2-4b24-5a2e-3cb2-a39abb73b862.gif)
![particle_mesh7.gif](https://qiita-image-store.s3.amazonaws.com/0/102664/eacafd1b-9502-1d57-05ca-ccf441365220.gif)
ent/Manual/GPUInstancing.html)
* [【Unity】パーティクルをGPU Instancingで描画してみる & 対応シェーダーを自作してみる - テラシュールブログ](http://tsubakit1.hateblo.jp/entry/2018/01/30/012440)

また `GPU Instancing`は一部のプラットフォームでのみ有効になります。
WebGL1.0では有効にならなかったのでWebGL2.0で試したのですが、2018.2.7f1ではMeshが描画地点から移動しないという不具合が発生しています。
バナー等の背景で使用する場合は `Standalone` で試すのが良いでしょう。
([@mao](https://twitter.com/TEST_H_)さんアドバイス/検証ありがとうございました！)

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ParticleSystemでMeshを描画時にParticle/StandardUnlitのMaterialを使用してEnable Mesh GPU Instancingを有効にしているのだけど、Batched Draw Calls増えなくて有効になっている気配しない... 何か漏れてたりするのかしら <a href="https://t.co/fwL8I5Pl4h">pic.twitter.com/fwL8I5Pl4h</a></p>&mdash; 青木とと\(ˊᗜˋ*)ﾉ (@lycoris102) <a href="https://twitter.com/lycoris102/status/1047272122295377920?ref_src=twsrc%5Etfw">2018年10月2日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" data-conversation="none" data-cards="hidden" data-lang="ja"><p lang="ja" dir="ltr">Profilerに(Instancing)の項目が表示されていないのが気になりますね。。<br>※有効だと↓の様に表示されるかと。<br>(予想ですが、Platformの方がGPU Instancingに対応していないとか..?🤔 ※詳しく見ないと何とも言えず...) <a href="https://t.co/Bpar1StIUz">pic.twitter.com/Bpar1StIUz</a></p>&mdash; mao (@TEST_H_) <a href="https://twitter.com/TEST_H_/status/1047276586779607040?ref_src=twsrc%5Etfw">2018年10月3日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" data-conversation="none" data-lang="ja"><p lang="ja" dir="ltr">あ、折角なので補足です。<br>WebGLでもGraphicsAPIをWebGL2.0にした上で↓のEmulation設定を2.0にする事でGPU Instancingに対応するのでこちらでも行けるかもです。👀<br>確かデフォルト設定は1.0だった気がするのでｗ<br>(※その代わりビルドはWebGL2.0に対応していないブラウザでは動作しなくなる) <a href="https://t.co/3RYLl0z4XG">pic.twitter.com/3RYLl0z4XG</a></p>&mdash; mao (@TEST_H_) <a href="https://twitter.com/TEST_H_/status/1047280065564663808?ref_src=twsrc%5Etfw">2018年10月3日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" data-conversation="none" data-cards="hidden" data-lang="ja"><p lang="ja" dir="ltr">あ、、、、<br>今手元で試してみましたが「表示はされてGPU Instancingも有効になっているが、何故かParticleSystemが動かない→meshがずっと原点に留まる」と言う謎の不具合？を確認しました😇😇😇(ビルド時も同様)<br>なん...だと...(particleはinstancing設定以外はデフォルト設定) <a href="https://t.co/pZoNBVJUaX">pic.twitter.com/pZoNBVJUaX</a></p>&mdash; mao (@TEST_H_) <a href="https://twitter.com/TEST_H_/status/1047284887735205888?ref_src=twsrc%5Etfw">2018年10月3日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" data-conversation="none" data-lang="ja"><p lang="ja" dir="ltr">同じ現実を目の当たりにしています！！！！！！！！ <a href="https://t.co/EModnOBeoP">pic.twitter.com/EModnOBeoP</a></p>&mdash; 青木とと\(ˊᗜˋ*)ﾉ (@lycoris102) <a href="https://twitter.com/lycoris102/status/1047285573411467264?ref_src=twsrc%5Etfw">2018年10月3日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 作成したParticleをUnityRecorderで出力する

作成した絵をバナー等の絵に使用するために出力します。
Mac標準のスクリーンショットを使用したり、各種ソフトを使う手段も取れますが、今回は `UnityRecorder` というAssetを使用します。

<img width="944" alt="Unity 2018.2.7f1 Personal (64bit) - [PREVIEW PACKAGES IN USE] - SampleScene.unity - UnityParticleMesh - PC, Mac &amp; Linux Standal… 2018-10-06 14-48-49.png" src="https://qiita-image-store.s3.amazonaws.com/0/102664/b81e2608-8bc0-ecba-c2f1-2dfdca9e1021.png">

[Unity Recorder - Asset Store](https://assetstore.unity.com/packages/essentials/unity-recorder-94079)

AssetStoreからダウンロード/インポートすると `Window > General > Recorder` というメニューが追加されます。
そこから `Recorder Window` を選択します。

<img width="562" alt="スクリーンショット 2018-10-06 15.09.51 2018-10-06 15-10-10.png" src="https://qiita-image-store.s3.amazonaws.com/0/102664/fd47d22b-05d8-7c1d-f3ff-80d09c352739.png">

以下のようなメニューが表示されます。
`Add New Recorders` を選択して、新しいRecorderを追加します。この時に以下の4つの出力形式を選択できます。

* AnimationClip (Unity上で使用する場合に選択する)
* Movie (MP4/WEBMの形式から選択可能)
* Image Sequence (静止画を連番で出力する)
* GIF Animation

静止画で使用する目的の場合は `Image Sequence` を選択します。
Captureの項目で `Game View` を選択し、GameViewに描画される内容をキャプチャするように設定します。
また `Output Resolution/Aspect Ratio` で解像度/アスペクト比を指定します。
(これによりスクリーンショットを取るより、高解像度の絵を取得することができます)

実際にUnityEditorで実行し、Particle再生中に `START RECORDING` を押してみます。
`Game View` は止まってしまったように見えますが、フレーム単位で静止し、撮影後にフレームを進める状態となります。
(UnityEditor上で一時停止した状態でも `START RECORDING` を押すことは可能です)

![particle_mesh8.gif](https://qiita-image-store.s3.amazonaws.com/0/102664/55a0078f-ad9c-7d03-aba6-3d2b291d386d.gif)

指定した保存場所に静止画が保存されるので、それを利用します。

<img width="620" alt="Recordings 2018-10-06 15-25-31.png" src="https://qiita-image-store.s3.amazonaws.com/0/102664/78ca8a58-f8a3-3143-12fa-28f67ed699e9.png">

注意事項としては、何回も撮り直して、それぞれの撮り直し内容を保持して起きたい場合
`File Name` に \<Take\> を追加してあげる必要があります (もしくは <Date> を追加して撮影日時で保存する)
`Take` は `START RECORDING` 毎に増加する数で `File Name` に \<Take\> の指定がない場合、 **上書き** となってしまいます。

![particle_mesh9.gif](https://qiita-image-store.s3.amazonaws.com/0/102664/3480a061-92bf-86af-d7d8-571827e9d679.gif)


# 最後に
いい絵が撮れたら、Illustrator等に持って行って文字を入れたり加工したりすると良いでしょう。
(もちろん、uGUIやTextMeshProを使って、Unity上でバナーを仕上げて、出力してそのまま使うアプローチも素敵だと思います)

![banner.png](https://qiita-image-store.s3.amazonaws.com/0/102664/e1b424af-0abc-de9f-acb1-f9cca091b8f6.png)

`ParticleSystem` を使ってノーコーディングで幾何学的な背景を作成し、 `UnityRecorder` を使って静止画出力するところまで
Unityを使っているエンジニアがサイトや技術書の背景に使ったり、Unityに精通していないデザイナーがUnityを触るきっかけになれば幸いです。