
マイケル
みなさんこんにちは!
マイケルです!

エレキベア
こんにちクマ〜〜〜

マイケル
今回はUnrealEngineのNiagaraに搭載されている SimulationStage という機能について紹介します。
こちらはNiagaraでGPUによるシミュレーションを行うための機能で、いわゆるUnityでいうComputeShader的な使い方をすることができます。

エレキベア
NiagaraでGPUシミュレーションが行えるクマか・・・
確かにパーティクルは大量オブジェクトを扱うクマが、あまりイメージが沸かないクマ

マイケル
有名な例だと、流体シミュレーションエフェクトの NiagaraFluid もSimulationStageを用いて実装されているようです。

エレキベア
確かに流体シミュレーションはGPU計算が必要になるクマね

マイケル
なお、今回使用したUEのバージョンは下記になります。
バージョン違いによっては実装が異なる場合もあるためご了承ください。
- UnrealEngineバージョン
- 5.32
参考書籍

マイケル
調査・実装するにあたり、下記の書籍を参考にさせていただきました。
日本語書籍で、Niagaraの基本的な使い方から流体シミュレーションまで含まれているのでおすすめです。

Unreal Engine 5で学ぶビジュアルエフェクト実装 基本機能からNia...

エレキベア
流体シミュレーションまで書いてあるとは、かなり実践的な本クマね

マイケル
また、SimulationStageではHLSLのシェーダーコードを書くことができます。
こちらは下記書籍が体系的にまとまっていておすすめです。

HLSL シェーダーの魔導書 シェーディングの基礎からレイトレーシングまで

エレキベア
がっつり使うとなるとシェーダーの知識も必要になるクマね
Niagara SimulationStageの概要

マイケル
具体的な実装に入る前に、そもそもNiagaraやSimulationStageとは何なのか?について軽く紹介しておこうと思います。
Niagaraとは

マイケル
Niagaraとは、UnrealEngineに搭載されているビジュアルエフェクトシステムです。
Niagaraシステムは大きく「システム」「エミッタ」で構成されています。
Niagaraの概要 - Unreal Engine 5.3

▲左:システム、右:エミッタ

エレキベア
UnityでいうところのShuriken的なものクマね
エミッタは聞きなれないクマ〜〜

マイケル
システムはレベルに配置することのできる単位で、エミッタはパーティクルの放出源です。
システムはエミッタを複数持つことができます。
Niagaraシステムの構成
- システム
- レベルに配置することのできる単位
- エミッタを複数持つことができる
- エミッタ
- パーティクルの放出源
- 他のシステムからも使用することができる

エレキベア
これがNiagaraの基本構成なのクマね
SimulationStageとは

マイケル
SimulationStageはエミッタ内に追加できるステージで、GPUによる複雑なシミュレーション計算を行うことができます。
Niagaraの主要な概念 - UnrealEngine5.3
SimulationStageとは
- Niagraに搭載されている、GPUにより複雑なシミュレーション計算を行うステージ
- Niagara標準機能では作れないような複雑なエフェクトが作成できる
- 直接GPUに対応したHLSLコードを書くことができる
- 他の粒子のアトリビュートを取得できる
- パーティクルだけでなく、RenderTarget2Dのような特定のDataInterfaceに対しても処理ができる

エレキベア
そこまで使われていないのか、公式ドキュメントにもあまり記載がないクマね・・・

マイケル
シミュレーション計算はHLSLコードを実際に書いて制御することができます。
ゲームエンジンでComputeShaderを使用する場合には実装コストも大きいですが、SimulationStageを使用すると描画部分をNiagaraに任せることができるので、最小限の計算を実装するだけでシミュレーションを行えるというメリットがあります。

エレキベア
確かにComputeShaderでの実装は計算部分以外の実装も大変クマからね・・・

マイケル
特にUnrealEngineでComputeShaderを実装する場合、
・グローバルシェーダを用いる
・外部モジュールを導入する
・エンジンを改造する
といった対応が必要になり、エンジンのバージョンごとにノウハウが変わるリスクがあります。
それを考えると、SimulationStageを使用して手軽に計算を行えるというのは大きなメリットだと思います。

エレキベア
UnrealEngineだと標準機能でComnputeShaderを使うようになってないのクマね
Niagara SimulationStageの環境構築

マイケル
それでは実際にSimulationStageの環境を構築してみます。
Niagaraの初期状態として、今回はFountainテンプレートを使用しました。

▲Fountainテンプレートを使用

▲初期構成

エレキベア
上に放射するだけのシンプルなエフェクトクマね
エミッタのプロパティの設定

マイケル
まずGPU計算を有効にするために、エミッタのプロパティの設定を変更する必要があります。
Sim Targetを「GPUCompute Sim」、Calculate Bounds Modeを「Fixed」に指定します。
Fixed Boundsは計算を行う領域になるため、状況に合わせて変更しましょう。

▲GPUを使用するように設定

エレキベア
ここを変更しないとGPUで計算されないクマね
SimulationStageの追加

マイケル
そして次にSimulationStageをエミッタに追加します。
こちらは右上の「+Stage」ボタンから追加することができます。

▲SimulationStageの追加

▲任意の名前を付ける

エレキベア
デフォルトではSimulationStageは入っていないのクマね
スクラッチパッドの追加

マイケル
ここから少し複雑になりますが、SimulationStageの「+」ボタンから「スクラッチパッド」というモジュールを追加します。

▲スクラッチパッドモジュールの追加

▲こちらも任意の名前を付けておく

マイケル
スクラッチパッドは標準で用意されていないモジュールを作成したり、HLSLコードを記述することができるモジュールで、初期状態は下記のようになっています。

▲スクラッチパッドの内容

エレキベア
ノードベースになってるクマね
ここに処理を書くことでモジュールとして扱えるということクマか

マイケル
ここで試しにHLSLコードを書いてみます。
CustsomHLSLノードを追加して下記のように記述します。

▲CustomHLSLノードの追加
▲速度を加算する処理

マイケル
Map Get、Map Setモジュールにそれぞれ「PARTICLE Position (各粒子の位置)」を追加し、CustomHLSLノードに接続することで入出力の変数が追加されます。
こちらの名前がHLSL内で参照できる変数名になるので、間違えないようにしましょう。

▲パーティクルの位置を更新するよう設定

マイケル
コンパイル後にエフェクトを見てみると、加えた速度により放出される方向が変わっていることが確認できるはずです。

▲放出される方向が変わる

エレキベア
HLSLコードで操作するイメージが湧いたクマ〜〜
ParticleAttributeReaderの追加

マイケル
以上でHLSLコードは書けるようになりましたが、実際にシミュレーション計算を行うには自身以外のパーティクル情報を参照する必要があるケースが多いです。
そのためにAttributeReaderという機能を介して参照できるよう設定します。

エレキベア
他のパーティクルを参照できる機能があるのクマね

マイケル
AttributeReaderはエミッタの属性(変数)として定義してスクラッチパッドに渡すようにします。
というわけでまずはParticleAttributeReader型の変数を追加します。

▲エミッタ属性にParticleAttributeReader型の属性を追加

マイケル
そしてエミッタのスポーンの「+」ボタンから「パラメータの追加」を追加し、用意したParticleAttributeReaderの属性を設定します。

▲エミッタのスポーンに「パラメータの追加」を追加

▲エミッタ属性に追加した属性を設定(エミッタ名は手入力)

▲ここまで設定した状態

エレキベア
これでエミッタのスポーン時にParticleAttributeRederが設定されるようになったクマね

マイケル
あとはスクラッチパッド内で、入力としてParticleAttributeReader型の属性を受け取るようにします。
これでHLSLコード内で特定インデックスのAttribute情報を取得することが出来るようになります。

▲スクラッチパッドにParticleAttributeReaderとNumParticles(パーティクル数)を追加
▲ParticleAttributeReader経由で各パーティクル情報を参照できるようになった

▲エミッタの設定で作成したAttributeReaderをスクラッチパッドに追加する

エレキベア
これでシミュレーション計算もやりたい放題クマね

マイケル
なお各パーティクルに設定した属性の値は、Attribute Spreadウィンドウより確認することができます。
属性がどのように変化しているかを確認できるので、こちらも状況に応じて活用しましょう。

▲Attribute Spreadウィンドウにて、各パーティクルの属性を確認できる
Boidsシミュレーションの実装例

マイケル
最後にSimulationStageを活用した実装例として、魚の群れをシミュレーションする例をざっくりと紹介します。
Boidsという群集シミュレーションアルゴリズムを使用しているのですが、こちらはUnityで実装した例を下記記事で紹介しているので興味がある方はご参照ください!

【Unity】Boidsアルゴリズムを用いて魚の群集シミュレーションを実装する
2024-05-28

エレキベア
UnityではComputeShaderで実装したクマね

マイケル
今回実装した内容は下記のリポジトリにあげています。
手元で動かしたい方はこちらご使用ください。

エレキベア
これもエフェクトとして動いてるなんて面白いクマね
ベースとなるエフェクトの実装

マイケル
シミュレーション計算を行う前に、まずはベースとなるエフェクトを実装します。
今回はEmpty状態のエミッタを作成した状態から始めました。

▲Empty状態で作成して設定した状態

マイケル
そして各パラメータをそれぞれ下記のように設定します。

▲パーティクルの数を設定

▲パーティクルの生存期間を延ばす

▲生成範囲をBox状で広めに取る

▲ランダムに少しだけ動かす

▲魚のスプライトマテリアルを設定

マイケル
以上で、Box形状でじわじわと魚が動くエフェクトが完成します。

▲Box形状でじわじわと動くエフェクトが出来た

エレキベア
ここから魚達を動かしていくクマね
シミュレーション計算の実装

マイケル
シミュレーション計算の準備として、「2. Niaraga SimulationStageの環境構築」の手順に沿って
・エミッタのプロパティの設定
・SimulationStageの追加
・スクラッチパッドの追加
・ParticleAttributeReaderの追加
を行います。

▲SimulationStage、スクラッチパッド、ParticleAttributeReaderをそれぞれ設定

エレキベア
SimulationStageを使える状態にするクマね

マイケル
そしてスクラッチパッド内にシミュレーション計算に必要なパラメータを用意し、最終的に速度として返却するように設定します。
パラメータの詳細については省略しますが、気になる方はUnity実装時の記事をご参照ください!

▲シミュレーション計算に必要な項目を渡し、最終的には速度として設定する
パラメータ | 概要 |
---|---|
SeparationDistance | 適用する他の個体との半径: 分離 |
AlignmentDistance | 適用する他の個体との半径: 整列 |
CohesionDistance | 適用する他の個体との半径: 結合 |
SeparationCoefficient | 適用時の重み係数: 分離 |
AlignmentCoefficient | 適用時の重み係数: 整列 |
CohesionCoefficient | 適用時の重み係数: 結合 |
WallAvoidanceCoefficient | 壁を避ける強さの重み |
SpaceScale | シミュレーション範囲 サイズ |

エレキベア
Boidsシミュレーションは「分離」「整列」「結合」の状態を判定するのだったクマね

マイケル
HLSLによる計算は下記のように実装しました。
ParticleAttributeReaderから各パーティクルの値を取得しつつ、Boidsシミュレーションによる計算を行っています。
▲Boidsシミュレーションの計算

エレキベア
(これノードに直接書くの割とつらいクマね・・・)

マイケル
最後にスクラッチパッドに渡すパラメータ値を設定して微調整すれば実装は完了です。

▲変数に値をそれぞれ設定

▲速度が速くなりすぎないよう制限をかける

▲スプライトのサイズを調整

▲群れのシミュレーションが実装できた

エレキベア
やったクマ〜〜〜〜
おわりに

マイケル
というわけで今回はNiagaraのSimulationStageによるシミュレーション計算の実装でした!
どうだったかな??

エレキベア
環境構築は覚えないといけないクマが、シミュレーション計算部分の実装に注力できるのはいいクマね
一度作ったエミッタは使いまわせるのも魅力だと思ったクマ

マイケル
Boidsシミュレーションを実装するのに、Unityの時は描画周りの実装も大変だったから計算部分だけ実装すればいいのは大きな魅力だね!

マイケル
というわけで今回はこの辺で!
アデューー!!

エレキベア
クマ〜〜〜〜
【UE5】Niagara SimulationStageによるシミュレーション環境構築 〜完〜