講演冒頭では、斎藤氏と谷口氏が作成した建物の破壊デモシーンが紹介されました。建物の破砕は「Chaos Destruction 」、煙や破片・窓ガラスのVFXは「Niagara Fluid 」を中心とした技術が用いられています。
講演では、建物の破砕について斎藤氏が、VFXについては谷口氏が説明を行いました。
Chaos Destruction編
最初に、斎藤氏から「Chaos Destruction 」の概要説明が行われました。Chaos Destruction はUnreal Engineの新しい破壊システムであり、Epic Gamesから発表された技術デモ「The Matrix Awakens: An Unreal Engine 5 Experience 」でも採用されています。
GDC2019 でもプレイアブルデモが発表されています。
Unreal Engineにおいて、単純な物理シミュレーションであれば「Simulate Physics 」にチェックを入れるだけで簡単に実現できますが、更に破壊、形状変化させるためには専用のシステムであるChaos Destruction が必要となります。
今回のデモシーンでは、先に挙げた「The Matrix Awakens: An Unreal Engine 5 Experience 」で使用された街のサンプルアセットとして提供されている「City Sample 」のビルを良い感じに壊すということを目指して作成されました。
破壊モデルの作成
Chaos Destruction では、City Sample のビルなどのスタティックメッシュをそのまま直接破壊することはできないため、まずはメッシュをジオメトリコレクション (以下、GC )という破壊専用のアセットに変換する必要があります。
変換はエディタの「Fracture Mode 」にて、メッシュを選択してメニューから「New」を押すだけで簡単に変換することができます。また、複数の破片のアクターからひと塊のGCを作成することも可能です。
ただし、破壊モデルの作成の際には注意点があります。破壊するモデルはあらかじめ厚み0のポリゴンや閉じられていない部品のない、物理的に問題ない「破壊レディ 」の状態であることが求められます。
以前斎藤氏が行った講演「豚×京都 ~UE4でなろう破壊神~ 」でも「破壊レディ」にするための対応などについて語られている
幸いなことにCity Sampleのビルはパーツ単位でモジュール化されており、ほとんどのパーツがすでに「破壊レディ」状態だったとのこと
モデルが破壊レディでない場合にはGC変換前にModeling Modeなどで加工する必要がある。これらの詳細はCEDEC 2022のエピック ゲームズ ジャパン鈴木孝司氏の講演「Unreal Engine 5 – Chaos Destruction 入門 」を参考とのこと
実際にCity Sample のビルをGCに変換する際にもさまざまな問題が発生したそうです。
City Sample 内の建物は基本的に単純なスタティックメッシュではなく、最適化のためほぼ全てがインスタンス化 されています。現在は複数のインスタンス化されたメッシュからのGC変換にエンジンが対応していません 。
このため、今回の場合はEditor Utility Widget 機能を用いてインスタンスをスタティックメッシュアクターに変換しています。
変換するためのEditor Utility Widgetはインスタンスを取得後にスタティックメッシュに置き換える非常に簡易的な内容で済んだという
右の元のインスタンスに対し、左のメッシュはスタティックメッシュアクターに変換されている
また、実際GC変換する際にもメモリエラーが発生しエンジンがクラッシュしてしまう問題に見舞われました。City Sample では仮想化ジオメトリシステムNanite を活用し、高品質を確保しつつリアルタイム性を確保しています。このため破壊対象のビルは数万ポリゴンのパーツが800ほど集まり構成された1棟数あたり千万ポリゴンの超ハイポリゴンアセット であり、これらを一度にGC変換するとメモリの限界を超えてクラッシュ してしまったとのことでした。
そこで、いくつかの対応策が検討されました。1つ目はGC変換を一気に行わず小分けにして変換していく 方法です。ただし、これは非常に手間のかかる作業になることが予想されました。
この変換を自動化できないかとPythonによるスクリプティング やEditor Utility Widget などを模索したものの上手くいかず、この対策を取るためにはどうしても手作業が必要という結論になりました。
PythonやEditor Utility Widgetには関数が公開されていなかったとのこと
City SampleのプラグインにGC変換コードをコピー・ラップした関数があり、BPに公開されていたもののこちらは動作しなかった
そもそもChaos Desctruction ではメモリやパッケージサイズ観点から、複雑で巨大なメッシュをGC化するよりも、モジュール化・クラスタグループ化してのセットアップが推奨されており、複雑なビル1棟をまるごとGC化するような動作はそもそも想定外 であるため、この方法は断念したと斎藤氏は語りました。
そこで対応策の2つ目として、モデルのリダクション によってそもそものポリゴン数を減らしていく方法を取ることにしました。Unreal Engineのリダクション方法としては現在、エンジン内のモデリングツールを使ってリダクションする方法 とメッシュを一旦エクスポートしてDCCツールなどでリダクションしその後に戻す方法 がありますが、今回は構成するパーツ数や作業効率の関係上、エクスポートしてHoudini でリダクション調整を行いました。
モデリングツールを使用してリダクションする場合については鈴木氏の「Unreal Engine 5 – Chaos Destruction 入門 」で詳しく解説されているとのこと
エクスポートする際の注意点として、NaniteメッシュはNaniteのままエクスポートするとNaniteメッシュではなく代わりにやや粗いポリゴンを持つフォールバックメッシュ がエクスポートされます。ただし、フォールバックメッシュ がある程度リダクションされているため、今回の場合は逆に手間が省け、特に問題もなかったためこちらを更に微調整する方向で進めました。
リダクションに成功し、いよいよGC変換する段階になりましたが、ここで更なる問題が発生しました。GC変換処理が非常に重く、ビルの一部を切り出した10万ポリゴンほどのメッシュ群の変換に2時間以上 かかったというのです。
あまりにGC変換が重すぎて、フリーズしたかどうかの判別も困難な状態だったとのこと
しかしこれはUE5.0のバグ であり、UE5.1に更新することで劇的に変換が早くなった そうです。
TipsとしてGC変換時に変換後のピボット位置を調整できる方法も紹介。選択した最初のアクターの位置がピボット位置として参照されるため、空アクターなどで調整ができる
無事にGCへの変換が完了しましたが、シミュレーションを開始する前から処理が非常に重いという問題にぶつかりました。
右側のデバッグ表示が真っ赤になっているのが確認できる
Unreal Engineのプロファイリングツール「Unreal Insights 」でプロファイリングしたところ、レンダリングスレッドでの大量のマテリアルの描画 がボトルネックになっていたことが判明しました。City Sample ではインスタンス化 やNanite によって最適化されているため、マテリアル数がそもそもあまり問題にならず、ビル1つだけで約200ものマテリアルが使用されています。
更にそこからGC化で断面部分のマテリアルが自動生成されるため、倍の400~500ほどのマテリアル数になります。この膨大な数のマテリアルが非常に重い描画処理の原因 となっていました。なお、この断面部分のマテリアルはUE5.1ではAdd Internal Materialsの設定で作成を回避することができる ようになっていますが、斎藤氏はそれでも数百ものマテリアルは非常に大きなボトルネックになると語りました。
City Sample 内ではこれをNanite で回避しています。GCもNanite化が可能 なため有効化しようとしたところ、今度はエンジンがクラッシュ。調査したところNaniteは1クラスタあたり最大64マテリアルまで という制限がありました。このため、同じマテリアルをアサインしてから再度GC化することでマテリアル数を30以下まで削りました。
試しに制限を解除してみたが、さまざまなバグに見舞われたとのこと
同一マテリアルをアサインした上で再GC化するとマテリアルがまとめられ、数を減らすことができる
ここまでの作業でGCのNanite化が完了し、レンダリングスレッドの負荷を大幅に軽減 することができました。
GCをNanite化する場合には「Strip on Cook 」のチェックを入れることで無駄なデータを省き、パッケージやメモリのサイズを削減できるというTipsも紹介
コネクションの調整
モデルがある程度完成したので、続いてコネクション調整 に移ります。Chaos Destruction ではGCの破片同士を自動的にコネクションすることにより、自然な破壊表現が可能になっています。コネクションはコンソールコマンドで視覚化可能です。
その他のChaosのコンソールコマンド資料として、鈴木氏のQiita記事 も紹介された
コネクションの設定はGCのプロパティやプロジェクト設定で調整 できます。デフォルトの設定だとコネクションが少し離れたものまで繋いでしまう傾向があるため、接続距離の調整の仕方などが紹介されました。
離れた破片を繋いでしまうと破片が宙に浮くような状態になってしまう
接続距離をプロジェクト設定などで調整することで、この問題を解決できる
UE5.1では「Bounds Overlap 」というさらに賢いコネクション計算のアルゴリズムが実装されています。
コリジョンの調整
つづいてはコリジョンの設定 についての解説です。今回は破片のコリジョン計算としてコンベックスコリジョン を使用。ある程度形状に沿った形を保ちながら軽く動作するため、基本的にはこのコンベックスによるコリジョン計算がおすすめとのことです。
また、より高精度なコリジョンが必要な場合、Distance Field とパーティクルを利用したレベルセット のコリジョンも使用できます。ただし、こちらはメモリや処理負荷とのトレードオフになるとのことです。
コンベックスコリジョン の自動生成時の注意点として、コリジョンが重なり合わないように生成されるため、意図した形状と違うものになってしまうことがありるため、不自然な動きの場合のコリジョンの確認方法などが解説されました。
コンソールコマンドでコリジョンの形状を表示させ確認することが可能
Fracture Modeで破片の形状とコリジョンを1つずつ見比べることもできる
UE5.1からは任意形状のコリジョンも設定可能に なっており、外部からコリジョンを持ち込むこともできるようになりました。また細かすぎる破片などの調整ツールとしてGeoMerge や組み込みメッシュ化 と言った機能も提供されています。
ここまでの作業で破壊モデルの準備はできたものの、そのままシミュレーションを行うとビルが壊れきった辺りではまだ少し重い状態でした。物理はFPSに依存して見た目がかなり変化するので、FPSを安定させたい場合の手段として、非同期シミュレーション が紹介されました。
非同期シミュレーションを有効にすると、ゲームスレッドと同期されなくなるものの、安定したシミュレーション結果が得られる
プロジェクト設定ではほかにもイテレーションやサブステップの設定を上げることもできるが、こちらも処理負荷とのトレードオフになるとのこと
フィールドによる挙動調整
破壊時の挙動の調整としてChaos Destruction にはフィールド と呼ばれる機能が用意されています。今回のプロジェクトではマスター、アンカーの2種類のフィールドを使用 しています。
フィールドシステムを使えば破壊時の挙動を制御することができる
動いてほしくない地面にはアンカーを設定。マスターでは破壊ダメージを与えることができる
マスターフィールドの注意点として「Force Dynamic Switch」にチェックが入っているとアンカーフィールドを貫通してしまうことが解説されている。逆に使用することで動きを与えないままSleepさせないことも可能だ
フィールド は手で動かすことも可能なので、レコーディングすることで自然な破壊感を演出することもできます。
破壊の方向性がある程度決まったら、カメラで挙動を確認し、よく壊れてほしい部分を追加で壊しながら調整できます。ボロノイなどで破壊後の破片を追加で分割 でき、任意のメッシュを使って切り刻むことも可能 です。
今回のプロジェクトでは見た目に影響がなかったためオミットされていますが、「ワッフル」と呼ばれる内部構造を入れることも検討 していたようです。このようなケースで複数のGCをひとまとめのものとしてシミュレーションさせたい 場合は、クラスターID を設定することで対応できます。
ここまで見てきた対策の結果、処理負荷面でも現行機などで問題なくシミュレーションできる程度になった
最後に斎藤氏は、さまざまな落とし穴があったもののほぼUEのみでオーサリングや処理負荷の確認ができるのは非常に便利であったとして、Chaos Destruction についての解説を締めくくりました。
VFX編
ここで講演者が斎藤氏から谷口氏に変わり、同プロジェクトのVFXについての知見紹介に移りました。
まず、今回のプロジェクトで使用されたUE5は、当時のUE5メインブランチから取ってきたもので、最新の環境とは違う可能性があるとアナウンスがありました。
続いて、メインとなるVFX作成ツール「Niagara 」についても説明がありました。
Niagara Fluidを用いた煙の表現
今回のプロジェクトでは倒壊の際の煙をNiagara Fluid を使用して作成しています。Niagara Fluid はNiagara で流体シミュレーションを扱いやすくするためのツールセット で、有効化することによってさまざまなライブラリが使用可能になり、2D・3D双方で煙・水・炎といったさまざまな流体表現を簡単に作り出すことが可能 になります。
Niagara FluidはNiagara自体を拡張するものではなく、あくまで流体シミュレーションに便利なモジュールやマテリアルなどを追加するものであるとのこと
Niagara Fluidを試してみる場合にはまず最初にテンプレートを使うことがおすすめとのこと。その際はフィルタリングでNiagaraをアクティブにする必要がある
システム内部構成として、基本的にはパーティクル発生源であるソースエミッター と、シミュレーション部分を担当するシミュレーションエミッター に分かれています。
ソースエミッター ではパーティクル数や挙動を設定した後に、「Set Fluid Source Attribute 」モジュールによってDensityやVelocityといったアトリビュートを設定します。
シミュレーションエミッター では構成するモジュールが非常に多いため、「Emitter Summary 」で各エミッターの流体コントロールのためのパラメーターがまとめられています。
機能 Niagara 内のモジュールを読み解くために必要な機能として、毎Tickで指定した回数任意の処理を実行できる「Simulation Stage 」、グリッドにデータを格納できるデータインターフェース「Grid Collection 」、Niagara からMaterial Parameter に値を直接渡せる「Material Parameter Bindings 」などがあります。
「Simulation Stage」はNiagara Fluidではシミュレーションの反復計算などで主に使用
「Grid Collection」は2D及び3Dのグリッドに対応しており、Niagara Fluidの全てのシミュレーションで使用されている
「Material Parameter Bindings」はDynamic Parameterに非常によく似た仕組みだが、パラメーターを指定して値を渡せる、内部処理による処理負荷の有利不利などいくつか相違がある
Chaosとの連携 Niagara Fluid とChaos を連携させることで、パーツの分離(Break)や衝突(Collision)に合わせてシミュレーションを実行 することができ、「壊れた瞬間に煙を発生させる」などといった動作も可能になります。
GC とNiagara の連携には、双方に設定が必要となります。
GC側では「Notyfy Breaks」「Notify Collisions」「Notify Trailing」などを有効化すればNiagara側に通知イベントを送れるようになる
Niagara側ではソースエミッターに「Spawn from Chaos」と「Apply Chaos Data」モジュールを追加
更にNiagara側では各モジュールに共通するパラメーターの設定を楽にするため、にユーザーパラメーターに「Chaos Destruction Data」のパラメーターを追加
「Chaos Destruction Data」では受け取る通知イベントやパーティクルの発生量、発生地点などを決めることが可能
コリジョン Niagara Fluid における流体とオブジェクトを衝突させるための設定は、基本的にはアクター側のタグに「collider 」タグを追加することで簡単に行えます。ただし、GCにおいてはEmitter Summaryのパラメーター変更やGemetry Collection Actorへの登録など特殊な対応が必要 になります。
「collider」というタグ名はNiagaraアクターの「Collide_Meshes」→「Actor Tags」に定義されている
GCではEmitter Summaryの「Collide Against」→「Geometry Collection」をチェック後にNiagaraアクターの「Collide_GeometryCollection」→「Geometry Collection Actor」にGCを登録
最適化
Niagara Fluid も含め、3D流体シミュレーションは魅力的な機能なものの、基本的に非常に処理が重くなっています 。そこでNiagara Fluidを 最適化する対策として以下の方法が挙げられました。
配置する数を減らす
Fruid Tick Delta TimeをONにする
シミュレーション解像度を下げる
モジュールの処理回数・負荷を減らす
谷口氏は「基本的には減らす、下げる、それしかありません」と話す
Niagara Fluidは1つでもかなりの処理負荷がかかるため必要性を常に意識することが重要。今回のプロジェクトでは流体が3つ配置されていただけで約45msほどの処理負荷がかかっていたことがあったという
「Fixed Tick Delta Time」をONにして間隔を指定すれば計算回数を減らせるため最適化に有効なほか、シミュレーション結果の安定にも寄与するため、基本的にはONに設定することがおすすめとのこと
シミュレーション解像度を下げると、煙全体がぼやけたような見た目になるが処理負荷が下がる。全体の解像度のほか、要素ごとの解像度を下げることも可能
ライト数や処理回数を減らすことでも処理速度を上げることができる。また、Pressure Relaxationを0以上に設定することでシミュレーションアルゴリズムが変わり、計算が早く終わるようにできるようだ
更にSimulation Stage のAdvect Scalars やAdvect Velocity にあるInterpolationTypeをCubicに変更 することで、処理負荷は少し増えるものの、最適化で崩れた煙の形状などをある程度整えられます。
また、最適化時のプロファイルに便利な機能として、以下のような項目が挙げられました。
Grid Bounds Overlay & Cell Size guides
Local Pivot
Performanceモード
Grid Bounds OverlayとCell Size GuidesをONにすることによってBounding Boxやセルの解像度を赤枠で表示できる
Local Pivotに数値を入力することで流体の位置は動かさずにBounding Boxのみを動かすことができる
PerformanceモードはNiagaraに搭載されているデバッグ機能の1つ。各モジュールでどのくらいの負荷が発生しているのかをプロファイリングすることができる
Niagara Fluidについての所感まとめ。カットシーンなどで使うために、シミュレーションを途中から開始する仕組みもあれば嬉しいとのこと
Mesh Rendererを用いた破片の表現
Mesh Renderer はスタティックメッシュを発生させることのできるNiagara のレンダラーで複数のメッシュからランダムに発生させることなども可能 となっています。今回は破壊の際の破片の量を増やすために使用されています。
この機能を使用する際に、メッシュ登録を手動で行う必要がある ため、大量のメッシュを登録する手間がかかってしまう という問題がありました。Unreal Python での解決法を探ったものの、登録用関数は見当たりませんでした。
当初は大量のガラスの破片もMesh Rendererで発生させる予定だったため、どうにか対処する必要があった
この問題に関しては斎藤氏からPythonを使って登録ができるようにしてはどうかとの提案があり、エピック ゲームズ ジャパンの鈴木氏に依頼して専用プラグインを用意 してもらったとのことでした。
実際のプラグイン内のC++での実装。クラスはUblueprintFunctionLibraryを継承して作成されている
登録用の関数(SetStaticMeshArray())ではエミッター内のMeshRendererに複数のスタティックメッシュを登録している
プラグインを利用したPythonスクリプトのサンプルコード。Niagaraエミッターとスタティックメッシュのパスから参照し、set_static_mesh_array()関数を呼び出している。関数表記法が元と異なるのはエンジン側の仕様とのこと
Pivot Paiter 2を用いたガラスの表現
ガラスの制作にはPivot Painter 2 が使われています。Pivot Painter 2 はメッシュとテクスチャを基にオブジェクトの回転軸、座標、スケールなどを復元する仕組みです。
谷口氏はPivot Painter 2について「Vertex Animation Textureのアニメーション情報を省いたもの」と表現している
ガラスの制作について、当初予定していたしていたMesh RendererではなくPivot Painter 2 を選んだ理由として、Mesh RendererのCPU処理負荷の高さ が挙げられます。このため、GPU処理であるPivot Painter 2に よってGPU側に処理を逃がす 必要がありました。
ガラスを全てMesh Rendererで描画すると、それだけで60msほどの処理時間がかかってしまっていたとのこと
Pivot Painter 2 を使ったガラス制作について、Houdini を用いてモデルを破壊、モデルと各テクスチャに出力し、City Sample のBrokenGlassから抽出したNiagaraモジュールにファイル情報を渡すことで各破片の座標や傾き、スケールを再現する といった工程が紹介されました。
モデルの破壊方法としてBoolean、RBDMaterialFractureなどが挙げられた
Labs Unreal PivotPainterを通して出力されたファイル。モデル用のFBXとポジション+Zスケール情報を保存しているEXR、そしてXY軸の傾きとスケールを保存しているTGAに分かれている
City SampleのBrokenGlassから必要なモジュールのみを抽出して、各ファイルのデータを渡すことで形状を復元する
位置や回転情報をマテリアルに渡す入れ物としてレンダーターゲット を使用、Material Parameter Bindings を使ってマテリアルにデータ受け渡しをすることで頂点移動を実現しています。
復元されたガラス。横線が入っているのはマテリアル側の仕様。この後ガラスをアニメーションさせたい場合は各破片に対してパーティクルを動かすだけとのこと
なお、同じことをしてガラスの位置がズレてしまう場合はテクスチャのミップマップ設定 やFilter設定 を見直すとよいとのことでした。
正確な情報としてテクスチャを使用したい場合はミップマップを作成せず、テクスチャのFilterは「Nearest」に設定することが望ましい
なお、Houdini 19.5.395からスムージンググループの出力が可能になっており、インポート時の警告が出ないように出力することができるようになった
また、Pivot Painter 2 でのガラスの破砕が試せるように、実際に用いたパラメーターやモジュールの中身なども公開されました。
最後に谷口氏は、煙・破片・ガラスのVFX作成に対するまとめを行い、講演を締めました。
質疑応答
その後の質疑応答では、工数やワークフロー、流体に対する影の反映やベイクに対しての質問がなされ、質疑用のスライドも交えながら回答がありました。
流体に対する影の対応としてUE5.1から実験的機能としてHeterogeneous Volumetric Renderingが追加
プロジェクト設定で有効化後に専用マテリアルを使用して反映する
NiagaraのフリップブックベイカーもUE5.1でボリュームテクスチャやシミュレーション自体のキャッシュができるようになり、機能強化されていることが語られた
Chaos Destructionで破壊された破片はUE5.1からブループリントで個々のアクセスが可能に
破壊制御自体もフィールドを使用せずに行えるようになった
Chaos&Niagaraによるリアルタイム破砕・VFX | UNREAL FEST(アンリアルフェス)公式サイト
アンリアルエンジンにハマり、ぷちコンでゲーム作ってた男。映像編で2連覇したことも。
昔はよくアーケードゲームとかやってました。
一番やり込んだのは「ケツイ ~絆地獄たち~」「戦国BASARAX」あたり。ローグライトゲームとかも好きです。