【Unity】VFX Graphで雨を降らせる

# はじめに
皆さん、雨は好きですか？
私は家の中にいる時に限り好きです。:rolling_eyes:
同じような方々のために、今回はお部屋で楽しめるUnityを使った雨の演出を作っていければと思います。

# 目標
こちらが今回の完成形になります。
(BGMは[魔王魂さん](https://maou.audio/)からお借りしました。BGMがあると雰囲気出ますねー:blush:)
<iframe width="800" height="450" src="https://www.youtube.com/embed/GRKi_MwoZ5o" title="【Unity】VFX Graphで雨を降らせる" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


# 作成手順
本題とあまり関係ないところは、ある程度かいつまみつつ説明していきます。

# 環境
・Unity バージョン：2021.3.13f1 (LTS)
・レンダーパイプライン：URP
・Visual Effect Graph バージョン：12.1.7

# 準備：プロジェクト作成 〜 VFX Graph作成まで。
### 1. プロジェクト作成
今回はURPで作成するので、「Unity Hub->3D(URP)」でプロジェクトを作成します。
初期状態ではVFX Graphのパッケージが入っていないため、「Window->Package Manager->Visual Effect Graph」をインストールします。

### 2.画像追加
プロジェクトの作成ができたら、まずは使用する画像を追加します。
今回は降ってくる時の線状の画像と、落ちた時の波紋の二枚の画像を使用します。
![rain.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2125059/4a8d3d95-1ee8-91df-e8ff-e90adcde96b0.png)    ![circle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2125059/596f3b4b-8692-1202-174f-b9406378e424.png)

### 3.VFX Graph作成
次にProjectウィンドウの適当な箇所で、
「右クリック->Create->Visual Effect->Visual Effect Graph」を選択して作成します。
作成できたら、ProjectウィンドウからHierarchyウィンドウにD&Dして、複製してシーンで見られるようにしておきます。
初期状態の時計みたいなやつが、わーっと湧き出してるやつが出てるかと思います。

# 雨を降らせる（VFX Graphを編集）
さて、ここからが本題です。
先ほど作成した、ProjectウィンドウからVFX Graphのファイルを開きます。

### Spawnノード設定
まずは、Spawnノード内のブロックを削除して、Periodic Burstに変更します。
ModeはどちらもRandomにして、ばらつかせることで自然な感じにします。
ちなみに`Count`は一度に発生させるパーティクルの数の範囲で、
`Delay`は発生間隔(秒)となっています。
![スクリーンショット 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2125059/caea63d8-d602-5722-a0e3-1b455ebbd761.png)

### Initialize Particle設定
 次にInitialize Particleノードで初期値の設定をしていきます。
`Capacity`は1000としておきました。線状の雨の数の上限で降らす量にもよりますが、もうすこし少なくてもいいかもです。
`Set Position(Shape:AABox)`は、箱状の領域内のランダムな箇所にパーティクル位置を設定します。
Centerを少し上の方にして、Sizeはxとzを広げておきました。
`Set Velocity Random`で初速を設定します。
降らせ始める位置からカメラのある位置まで、この後設定する重力のみだと遅いため少し速度を速めています。
![スクリーンショット Initialize Particle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2125059/a020d066-2101-34c2-3297-7e52c9dfee97.png)


### Update Particle設定
次にUpdate Particleです。
後々追加しますが、一旦`Gravity`ブロックを追加し、徐々に速く落下するようにします。
![スクリーンショット Update Particle1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2125059/747515d1-d4a6-a013-bf38-4dba84f4d764.png)

### Output Particle Quad設定
最後に出力関係の処理です。
`Blend Scale.Y`で縦方向に引き伸ばし、`Blend Alpha`で透明度を調整しています。
`Orient:Fixed Axis`では縦方向を固定しつつ、カメラの向いている方向に回転するようになるようです。
今回は実装しませんが、プレイヤーが移動してもこの設定によって不自然な見た目にならないようになります。
>[Orient: Face [Mode]](https://docs.unity3d.com/ja/Packages/com.unity.visualeffectgraph@10.7/manual/Block-Orient.html)
>Fixed Axis
>パーティクルは、指定された '上' 軸で回転し、カメラに向きます。これは草など、上軸が通常把握されており、上から観察したときにパーティクルが平らになることなく、そこを軸にして回転するエフェクトに役立ちます。

![スクリーンショット Output Particle Quad.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2125059/13cae1f4-ae8c-0bfc-b5a2-01aa3d29f4b1.png)

## 雨が降ってきた！
と、ここまでの処理で、雨が降るところまでできたと思います。
![result1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2125059/4e8ba4b7-2c23-595d-ea77-2e7861c1eb8b.gif)

このままでもいいのですが、少しさみしいので地面に落ちたときの波紋を追加します。

## 波紋パーティクル
### 雨が地面にうちつけられるための設定
波紋の追加に当たり、設定が必要になります。
[Unity->Preferences->Visual Effects]で、`Experimental Operators/Blocks`にチェックを入れておきます。
これにより`GPU Event`が利用できるようになりました。

### Update Particleにブロック追加
波紋を発生させるために、線のパーティクルのUpdateを調整します。
`Kill(AABox)`では、Solidモードを設定し、パーティクルが指定の箱の範囲に入った時に消えるようにします。
`Trigger Event On Die`では、パーティクルが消えた時に、Countの数分、波紋パーティクルを発生させます。
今回はとりあえず2で設定しておきます。
![スクリーンショット Update Particle2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2125059/cecc9218-e936-0cc8-6efd-7219d359fb61.png)

### Initialize Particle設定（波紋パーティクル）
`Trigger Event On Die`から`GPU Event`に接続し、そこから波紋パーティクルの処理を作成していきます。
`Inherit Source 〜`を利用して、パーティクルのサイズと位置について、線のパーティクルの値を継承しています。
`Set Lifetime Random`ではランダムに設定し表示期間に幅をもたせています。
`Set Angle.X`では90と入力することで地面と並行になるように角度を調節しています。
![スクリーンショット Ring Init.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2125059/8a7bf580-eecc-b450-90c8-f9ff9a9a1acb.png)

### Update Particle設定
Update Particleでは何もしません。
![スクリーンショット Ring Update.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2125059/98195174-5903-8e21-34bf-5e694aefed75.png)

### Output Particle Quad設定
`Main Texture`には円の画像を設定。
`Set Alpha over Life`で、寿命を最大とした発生してからの時間に応じて、発生した後に徐々にはっきりと表示され、その後再び徐々に消えていくカーブを設定します。
`Add Size over Life`でも、時間に応じてサイズを変更しています。
初期化時に、ランダムで寿命を決めているため、1つ目と2つ目で違うサイズとなり波紋を二重に表示しています。
※残念ながらランダムなため、2つの寿命が近いと二重に表示されなかったり、2つ目の波紋が大きくなったり挙動が正確じゃないです。いい方法が思い浮かばなかったのですが、なにかいい方法があれば知りたいです！
![スクリーンショット Ring Output.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2125059/2a66bd22-9376-4e4f-bf81-0340715bf944.png)

### 完成？
というわけで、Gameウィンドウを見てみると、、、
![result2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2125059/d254c6ef-8fa9-911c-5d2d-4f7051500e85.gif)
雨が降って地面にうちつけられているように表示することができました！

### と言いたいところですが、ちょっと問題が
シーンビューで横から見るとわかるんですが、波紋の表示される高さが微妙にずれてます。
![スクリーンショット Problem.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2125059/f5c716b0-2d2f-cafb-b99a-49217a1d23ba.png)
これは、線のパーティクルの消える位置に表示するようにしているのですが、線パーティクルの速さによって、`Kill(AABox)`内のどこであたったと判定されているかが変わるためずれているようです。

### 解決法
今回は、XとZの位置のみ線パーティクルから引き継ぎ、Yは0固定という方法で解決ということにしました。
（線パーティクルと消える位置が違う場合がありますが、線パーティクルの落下速度が速いので分かりづらいため許容範囲ということで、、、）
![スクリーンショット Fix Position Problem.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2125059/047f27c7-2584-3371-8a04-3b15155352c4.png)
![スクリーンショット Fix Problem.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2125059/76c39dfa-832d-98c0-db65-7a2922464738.png)

# 終わり
今回はVFX Graphを利用して雨の演出を作成しました。
発生位置を外から変更して、プレイヤーのいる位置に雨を降らせたり、
パーティクルの発生量を増減させて土砂降りや小雨にするなどできると思います。
おもいおもいの雨ライフをお楽しみいただけますと。:umbrella2:

# 参考:pray:
https://www.ame-name.com/archives/7124

https://www.ame-name.com/archives/153

https://www.youtube.com/watch?v=mWT5lXj2qts

https://nn-hokuson.hatenablog.com/entry/2019/07/05/090946