Visual Effect Graph 入門

## はじめに

現在、 Unity の新機能として開発が進んでいる "Visual Effect Graph (VFX Graph)" というものがあります。

ノードエディッターでポチポチとノードをつないでいくと簡単にパーティクルエフェクトが作る事ができ、内部的には Compute Shader ベースで実装されているため大量のパーティクルを CPU 負荷を上げずに表示できるという、とってもすごいものです。

ただ確かに簡単といえば簡単なのですが、できる事が多すぎて初手で何をすればよいかよくわからない、といった感じがしました。

ということでそれっぽい動きがする簡単なパーティクルエフェクトの作り方を VFX Graph の導入から順に解説していきたいと思います。

最終的には次のようなものを作ります。

[![image](http://img.youtube.com/vi/9SwU5pfqmYM/0.jpg)
https://youtu.be/9SwU5pfqmYM


VFX Graph は開発中の機能のため今回の記事が将来的にも通用するかどうかはわかりませんのでご注意ください。今回の記事は下記のバージョンを使用しています。

* Unity 2019.1.0f2
* Visual Effect Graph 5.13.0 preview
* Core RP Library 5.13.0
* High Definition RP 5.13.0 preview

HDRP 環境でやっていきますが、現在の VFXGraph は LWRP 、 標準レンダラーでも動作するようになっているらしいです (私はやったことないのでこの記事では HDRP 前提にします) 。

* [【Unity】Visual Effect Graph（VFX Graph）をLWRPで使用する](http://tsubakit1.hateblo.jp/entry/2019/04/03/233240)

## プロジェクトの準備

### プロジェクト作成 - package の導入

新規プロジェクトの作成でテンプレートは通常通り "3D" で作成してください。 HDRP のテンプレートはありますがテンプレートから始めると余計なものがたくさんついてくるので VFX Graph に限らず HDRP を使う場合も HDRP テンプレートは (テンプレートの内容を見たいのでなければ) 使わない方がよいかと思います。

Unity が起動したら "Window - Package Manager" で Package Manager を開き、 "Advanced" から "Show preview packages" にチェックを入れて Preview Package も表示するようにした上で下記 3 つを install します。

![190419_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/a91e820b-65c7-f23d-52b8-7e37a8dbbbfa.png)

* Core RP Library (Unity 2018 以前では異なった名称で表示される場合もあります　(Render-pipelines.Core))
* High Definition RP
* Visual Effect Graph

![190419_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/9be4aba7-2c5d-8cba-188d-bba4255ca477.png)

"CoreRP Library" と "High Definition RP" は依存関係があるのでバージョンに注意してください。

### HDRP のセットアップ

1. "Assets - Create - Rendering - High Definition Render Pipeline Asset" で HDRP asset を作成します  
![190419_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/ec6ad538-cc4b-8d32-507a-67f67cd26b15.png)
2. "Edit - Project Settings" で Project Settings を開きます
  1. その中の "Graphics - Scriptable Render Pipeline Settings" に作成した asset を設定します  
![190419_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/2cd1875a-f7a9-b82e-edc0-00b4bad9cecc.png)
  2. 合わせて "Player - Other Settings - Rendering" の Color Space を "Linear" にします (HDRP は Linear 必須)  
![190419_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/7e7d1cd9-f144-ae8c-afdf-cafc9ce4814e.png)
3. "GameObject - Rendering - Scene Settings" で Scene 上に Scene Settings を作ります。中の設定はとりあえずは不要です  
![190419_8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/e071f4bb-7a49-9a6e-0582-5fbbaefd452b.png)

### VFX asset の準備

"Assets - Create - Visual Effects - Visual Effect Graph" で VFX asset を作成します。

![190419_7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/ea0c1a0a-550a-6061-9854-8809db763c2e.png)

"Game Object - Visual Effects - Visual Effect" で Scene 上に Visual Effect を作成し、作成した VFX asset を Asset Template に登録します。

![190419_9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/26c6f7a3-233e-81a7-bcf9-421240bb280a.png)
![190419_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/9cb9d5ea-90bb-5711-5f2b-5a1051c3f305.png)

以上で準備完了です。作成した VFX asset をダブルクリックするとノードエディッターが開き、 Scene View, Game View でも初期状態のパーティクルエフェクトが動作し始めます。 (スクリーンショットではカメラの位置だけ調整しました)

![190419_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/9d9321fd-a2c9-2ef1-5fab-a2356f362f9f.png)

## パーティクルを作ってみる

### VFX asset を見る

VFX は大枠で "Spawn", "Initialize", "Update", "Output" という 4 つのもので構成されています。これら一つ一つのことを "Context" と呼び、 4 種類の Context を組み合わせて 1 つの "System" を構成します。 1 つの asset の中で System は複数作れます。

新規に作成するとすでに System が 1 つ動作している状態になっています。これを改造していきます。

![190419_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/4a9b2650-e99e-7237-17d7-ad6539f39dc7.png)

### Output を設定する (その 1)

Output ではパーティクル一つの見栄えを定義します。デフォルトでは "Quad Output" というテクスチャ一つをパーティクルとするものが割り当てられています。 Mesh をパーティクルとしたい、といった根本的に異なる形状のものを出力したい場合は Output Context を作ってノードを接続すればできます。

ここではこの "Quad Output" を使ったパーティクルにします。

1. Texture の画像を変更します。 VFX Graph の pacakge の中にはいくつかの画像が入っているのでこれを利用します。"Packages/Visual Effect Graph/Textures" の中から "Spakle" を Quad Output の Main Texture に D&D で登録します  
![190419_18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/a92517fd-99a3-faf2-0c15-66eab2af5d1a.png)
2. "Quad Output" の上で右クリックメニュー "Create Block" を選択、 "Set Scale" を追加して Scale 値を調整します。 X が幅、 Y が高さになるので X を小さめにすることで細い感じにします。 (ここではとりあえず (0.5, 5.0, 0.0))　追加の際、検索バーを使って検索した方が早いです  
![190419_19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/a2911f6f-e143-e189-8e5f-5846db5c3e79.png)
3. "Orient" の Mode を "AlongVelocity" に変更します
4. "Set Size over life" は使わないので削除してください

次のようになります。

![190419_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/32c54b9b-f3a0-6ea1-ba18-8aa62a61d4b6.png)
![190419_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/bbcf4646-836f-fb98-8e33-b128354ec16f.png)


この Sparkle を使った Output は VFX Graph のサンプルで火花のパーティクルに使われているものだったりします。 3. の Along Velocity 設定がポイントで、この設定をいれる事で移動する方向にパーティクルの向きも沿うようになります。

#### 余談: 別の Output Context をつないでみる

(本筋には関係ないので気にならなければ飛ばしてください)

1. ノードエディッターのなにもないところで右クリックしてメニューを出し、"Create Node" を選択します
2. 検索バーに "output" と入力し Output Context を列挙し、 "Cube Output" を選択します
3. Cube Output の上で右クリックメニューを出し "Create Block" をして "Set Color" を追加し、任意の色を設定します
4. Update Context の下のノード端 (出力) から作成した Cube Output の入力ノード端に接続をします

次のようになります。

![190419_16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/7d5b2830-1c39-e0a1-abb7-94b99be547af.png)
![190419_17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/f5f0b185-9799-41a3-5b51-1121ae40d1e8.png)

赤い四角のパーティクルが追加されました。このように一つの Update から同条件で異なる Output を複数つなぐことも可能です。

作成した Cube Output は以後使わないので削除してください。

### Spawn ～ Initialize の設定をする

Spawn と Initialize はパーティクルの生成に関する設定をします。

1. Initialize の上で右クリックメニュー "Create Block" を選択、 "Position (Sphere)" を追加します。  
![190419_22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/09b3ac9a-380c-93ed-c9f7-c95bb7b46dda.png)
2. Initialize の "Set Velocity Random" を Min = (-0.1, 0.0, 1.0), Max = (0.1, 0.3, 0.1) とします。

この状態だとパーティクルが少ないのでよくわからない感じになっています。

![190419_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/870f0db1-82c8-d11c-f710-17bec4e74e0c.png)

そこで Spawn の Rate 、 Initialize の Capacity を適当な大きい値 (Spawn Rate = 1000, Initialize Capacity = 10000) を設定すると次のようになりました。

![190419_26.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/eb870f7c-793e-79bd-dada-ab3143ee422a.jpeg)

大量に出てきて「らしい」感じになってきました。ここでの設定をまとめると次のようになります。

![190419_27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/b40452e9-4c62-6399-72b7-ab605286012a.png)

また、 "Set Velocity Random" を無効にするとパーティクルが全く出なくなります。この事から動きが全くないパーティクルは根本的に除外されるようになっているのではないかと思われます。

### Initialize のパラメーターを動的に変更する

Context の Block の中でも Velocity のように動きをつけることができますが、できる事は限られています。そこでパラメーターを動的に変更する事で動きをつけていきます。パラメーターは Node を作成し、 Node を接続していくこど制御することができます。

パーティクルの基準位置を動かしてみます。

1. Initialize の上で右クリックメニュー "Create Block" を選択、 "Add Position" を追加します。
2. ノードエディッターの何もないところで右クリックメニュー "Create Node" を選択、 "Periodic Total Time" を選択します  
![190419_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/71b77890-f5ba-d4f8-781d-2a6c4fb01835.png)
3. "Periodic Total Time" のパラメーターを次のようにします
    * Period = 5
    * Range = (-10, 10)
4. 1. で追加した Initialize の Add Position の X と "Periodic Total Time" の t を接続します  
![190419_30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/25a9362f-fcff-aa65-83b4-cd137fb23725.png)

すると次のように横に移動する動きが入ります。つまり "Periodic Total Time" を利用することで時間軸の動きをつけることができるようになるわけです。

![190419_31.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/e59642d4-9c57-a3ef-6514-dc384f289922.jpeg)

もう少し複雑な動きをつけます。

1. "Periodic Total Time" のノード接続を切断します。ノードの切断は接続されているノードを選択して Del キーで削除できます
2. "Create Node" で "Sequential Circle" を追加します
3. "Sequential Circle" のパラメーターを次のようにします
    * Count = 100
    * Radius = 5
4. "Periodic Total Time" のパラメーターを次のようにします
    * Period = 2
    * Radge = (0, 100)
5. ノードの接続を次のようにつなぎ変えます  
![190419_32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/37d51ef1-707f-d557-105c-1892b12861c1.png)

すると円の動きをするようになります。

![190419_33.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/6b952087-86ba-c019-4f8b-117b7a13bb83.jpeg)

計算をするためのノードもありますのでそれらを使って下記のような接続を作ってみましょう。

1. Sequntial Circle の Radius を 3 に変更し、複製します
2. "Multiply" と "Vector3" ノードを追加します
3. Circle(1).X -> Vector3.X, Circle(2).Y -> Vector3.Z を接続します
4. Circle(1).Y と Circle2.X を "Multiply" ノードに接続し、出力を Vector3.Y に接続します
5. "Vector3" を AddPosition の Position に接続します

![190419_34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/8517ebc7-ad5d-83eb-f759-cbe53c9e20a1.png)

("Sequential Circle" の Radius は 3 にしています)

こうすると Z 方向も含めた螺旋の動きになりました。

![190419_35.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/5abc8012-8f60-e592-d611-dc0da5ef86a3.jpeg)

### Update の設定をする

Initialize のパラメーターを動的に変更するようにしてみましたが、これはパーティクルの個々の生成位置を変更しているものであって、確かにパーティクルエフェクト全体として見た場合は動いているように見えますが、個々のパーティクルの動きについて動的な関与はしていないわけです。

パーティクルの動きの設定は Update Context で行います。ここでは Gravity を設定してみます。

1. Update の上で右クリックメニュー "Create Block" を選択、 "Gravity" を追加します
2. Force =  (0.0, -0.2, 0.0) に設定します

![190419_36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/5f51e77a-41c8-9325-d9b9-1aec9b653d8c.png)

こうするとパーティクルがゆっくり落下する動きが追加されます。 Initialize で Velocity が Random に付与されているのでパーティクル個々の動きもまちまちになっています。

### Output を設定する (その 2)

初期の Quad Output に元々ついていた "Color / Alpha over life" をいじることで時間軸そった色変化のアニメーションを設定することができます。 "Gradient" をクリックして設定をしてみましょう。

![190419_37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/7c5e5879-279a-9010-14a6-84544b38f084.png)
![190419_38.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/59ea15da-24b8-b372-2703-498326b87ac3.jpeg)

ちょっとわかりにくいですが少し強めの Intensity を付与した黄色を割り当てて、αチャンネルで変化をつけるようにしました。 

### Bloom をつける

Bloom は Post Effect なので VFX Graph ではつけられません。ので HDRP の設定で Bloom をつけてみます。

1. Hierarchy の "Scene Settings" (プロジェクトの準備で作りました) を選択し、 Inspector の "Volume" の "Add Override" を押します。
2. "Bloom" を追加します。 (検索バーで "bloom" を入れる)
3. Bloom の "Intensity" のチェックを ON にし、いい感じの値を設定します。

![190419_39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/c2959904-9db5-5c22-c424-3870d85612e0.png)

Quad Output の色設定も合わせて再度調整してみてください。

![190419_40.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211064/e1d3c3a7-9fb8-c543-7a76-f32170a90ead.jpeg)

Bloom は Scene Settings であって VFX Graph のための設定ではないことも留意しておいてください (実際はシーン全体で調整する必要があります) 。場合によっては Bloom っぽいテクスチャを使ってパーティクルを作った方がよいかもしれません。

## サンプルプロジェクトを見る

* [Unity-Technologies/VisualEffectGraph-Samples](https://github.com/Unity-Technologies/VisualEffectGraph-Samples)

Unity 公式のサンプルプロジェクトです。

非常に参考になるので必見ではあるのですが、結構複雑なことをしているのでいきなり見るとそっ閉じしたくなる衝動にかられるかもしれません。とりあえず本記事の手順を一通りやってみて雰囲気をつかんでから見てみると抵抗少なく見る事もできると思います。

また、このサンプルで見られる映像はかなりすごいのですが、これらの映像は VFX Graph 単体で実現しているのではありません。 VFX Graph の真価は他機能と連携をすることによって発揮するのではないかと思います。そういった具体的な応用の仕方もこのサンプルプロジェクトから学べると思います。

## お勧め記事

VFX Graph を学習するにあたって参考になった記事です。ありがとうございます。

* [【Unity】Visual Effects Graph(VFX Graph)をとりあえず動かしてみる](https://notargs.hateblo.jp/entry/vfx_graph)
* [【Unity】UnityShader勉強会「VFX Graph入門」で登壇しました！](https://notargs.hateblo.jp/entry/vfx_graph_tutorial)
* [UnityのVFXGraphでパーティクル芸やる方法](https://blog.gmork.in/entry/vfx-graph)
* [【Unity】Visual Effect Graph(VFX Graph)で100万個以上のドカベンロゴを回すGPUパーティクルを実装してみた](https://qiita.com/mao_/items/7aa77823f3a392bce8ca)

## おわりに

VFX Graph は使い方の感覚さえつかめれば簡単にパーティクルエフェクトが作れるだけではなく、幅広い応用性を持った非常にポテンシャルのある機能だと思います。

これは使わないとかなりもったいないと思いますので、まだやったことがない方は是非試してみてください。