ちょっと詳しい Mutable
Tags:この記事では、Mutable の基本的な概念とCustomizable Object の作成方法...はすっ飛ばして、コンパイ ル、デバッグ、クック、パッケージングについて解説します。
開発環境
- Unreal Engine 5.4
Mutable とは
基本的な Mutable の説明や使い方は、公式ドキュメントがとても丁寧に解説してくれています。 なので、ここでは超ざっくりとしたことを書いておきます。
Mutable は、実行時に動的にスケルタルメッシュやマテリアル、テクスチャを生成する Unreal Engine のプラグインです。 UE5.5から正式にサポートされました。 主に、カスタマイズ可能なキャラクターやアイテムを作成するために使用されます。 それらを作成する際にMutable を使用することで、メモリの使用量を抑えたり、ドローコールを減らしたりと、より効率的で柔軟なキャラクターやアイテムのカスタマイズが可能になります。
Customizable Object とリソースのマージ
Customizable Object は、 Mutable で扱う主なアセットです。 オブジェクトに適用できるすべての要素が含まれており、実行時に制御可能なパラメータと 、そのパラメータがオブジェクトにどのように適用されるかを定義します。
もっともシンプルな Customizable Object
Customizable Object のもっともシンプルな構成は、以下のようになります。
画像の例では、JacketA の SK_MeshComponent を持つオブジェクトを定義しています。
定義する過程で特に操作をおこなっていないため、元の SK_MeshComponent と同じ見た目になります。
マテリアルとメッシュのマージ
Mutable では、アセットを組み合わせることで新たなスケルタルメッシュを生成できます。
ノードグラフを使用してスケルタルメッシュの生成を制御できます。 一見同じ見た目のメッシュが生成されていても、グラフの組み方によって含まれるマテリアルやスケルタルメッシュの内訳が異なることがあります。
例として、マテリアルやスケルタルメッシュのマージを見てみます。作成したいオブジェクトを以下の画像のような「 BaseBody が JacketA と Pants を着用しているキャラクター」としましょう。
マージをおこなわない場合
まず、メッシュのマージをおこなわない場合は、以下のようなノードグラフになります。
この場合、このオブジェクトは BaseBody(Head) とBaseBody(Body) と JacketA と Pants の3つのスケルタルメッシュを持つことになります。
スケルタルメッシュのマージをおこなう場合
次に、メッシュのマージをおこなう場合は、以下のようなノードグラフになります。
同じ Mesh Componentに Mesh Section を追加するか、 Add To Mesh Component ノードを使用して、 Mesh Component を追加することで、メッシュのマージをおこないます。
結果として、このオブジェクトは BaseBody と JacketA と Pants の3つのメッシュをマージしたスケルタルメッシュを持つことになります。
マテリアルのマージをおこなう場合
最後に、マテリアルのマージをおこなう場合は、以下のようなノードグラフになります。
マテリアルのマージは親マテリアルが共通である場合に限られます。
ここで使用しているスケルタルメッシュは、BaseBody と洋服のマテリアルが異なります。
そのため、BaseBody(Head) と BaseBody(Body) をひとつの Mesh Section にまとめ、 JacketA と Pants をひとつの Mesh Section にまとめました。
結果として、このオブジェクトは2つのスケルタルメッシュと、それぞれのマテリアルを持つことになります。
注意として、マテリアルをマージするとき、マテリアルが持っていたパラメータはベースのマテリアルのものが全体に適用されます。そのため、仮に個別にカラーの調整などを行っていた場合、マージ後の領域で個別の調整が引き継がれることはありません。
ただし、テクスチャをマテリアルのパラメータとして使用する場合は例外です。マテリアルをマージするとき、ほかのパラメータと同じくマージ後はひとつしか残らないのは同じですが、同時にテクスチャのマージとメッシュ UV の再レ イアウトが行われます。そのため、異なるテクスチャを持つマテリアルをマージしても、それぞれのテクスチャが正しく適用されます。
テクスチャをマージとメッシュ UV の再レイアウトを行うと、以下のようなテクスチャが生成されます。
これは、JacketA と Pants のテクスチャをマージしたものです。
UV の再レイアウトは、こまやかな設定が可能であるため各テクスチャに要求する内容に合わせて調整できます。
Customizable Object の分割
前節ではひとつの CO に書きましたが、CO を分割することもできます。
分割をすることで、作業が分かれるため、複数の人が同時に作業を進めることができます。
一方で、実は CO を分割しても、パッケージングすると一つのアセットにまとまってしまいます。この点について、詳しく後述します。
Customizable Object のコンパイル
CO のエディタには、「コンパイル」というボタンがあります。コンパイルとはいうものの、具体的には何をするボタンなのでしょうか?
ノードが扱うデータのおさらい
Mutable のコンパイルを知るために、ノードが扱っているデータの種類をおさらいしましょう。
メッシュセクション
メッシュセクションは、ひとつのマテリアルで描画されるメッシュの領域です。メッシュセクションには、メッシュとそれをレンダリングするためのマテリアルが含まれます。
メッシュコンポーネント
メッシュコンポーネントは、複数のメッシュセクションの集合体です。複数のメッシュセクションを組み合わせることで、生成するスケルタルメッシュを表します。
LODごとに異なるメッシュセクションを含めることで、LODの切り替えに対応できます。
オブジェクト
オブジェクトは、Customizable Object のルートを表します。ここには、複数のメッシュコンポーネントや、それらを変更するための情報が含まれます。
コンパイルとは?
CO のコンパイルでは、以下の処理が行われます。
- 利用している UE アセットを収集し、Mutable 形式へ変換する
- Customizable Object 処理のバイトコード化
どちらの処理も、オブジェクトノードを起点とします。ノードの依存関係をたどることで CO のノードグラフ全体を解析することでおこなわれます。
この際、CO 内で呼ばれているほかの子 CO も解析されます。そのため、子 CO を持つ場合、親となる CO から順に解析されます。 子 CO も含めたすべての CO のノードグラフが解析された後、コンパイルが完了します。
Mutable は UE 上で動作するプラグインですが、利用するアセッ トも CO の処理も、どちらも Mutable 独自の形式に変換して利用します。 変換されたアセットや処理は、CO アセットに埋め込まれます。
アセットの収集と変換
CO で参照した UE のアセットはノードの依存関係を辿って収集されるので、オブジェクト、メッシュセクション、メッシュコンポーネントの順に収集されます。その過程でテクスチャなど、他のアセットがあればそれも収集されます。
収集されたリソースは Mutable の独自形式に変換されます。
変換されたデータは、C++上では Mutable のリソースクラスに格納されます。例えば、メッシュやマテリアルは、mu::Mesh
クラス、テクスチャは mu::Image
クラスに格納されます。
Customizable Object 処理のバイトコード化
CO のグラフは、実行のたびにゼロから解釈されるわけではありません。コンパイル時に、グラフの処理をバイトコード化します。 バイトコードとは、機械にとってわかりやすい命令の列に変換されたプログラムのことです。
アセットの収集とおなじく、ノードの依存関係に従ってバイトコード化されます。こちらの場合、依存関係のないノードから処理が実行でき るようにバイトコードに変換されていきます。
Mutable のバイトコードには、たとえば以下のような命令が含まれます。グラフ上のノードは、こうしたより小さな命令に変換されていきます。
// mu::Image をリサイズ
IM_RESIZE
// mu::Mesh をマージ
ME_MERGE
// Curve からスカラーの値を取得
SC_CURVE
CO から生成されるバイトコードは、実行時に Mutable のランタイムモジュールによって実行されます。実行のときに必要なのは、このバイトコードであるため、パッケージング後には CO のグラフなど、エディタ上での情報は削除されます。
C++ 上では、mu::FProgram
クラスの中に格納されます。mu::FProgram
はさらに、mu::Model
クラスに格納されており、このクラスがプログラムを実行するためのインターフェースを提供します。
生成されたバイトコードやリソースは、デバッグ機能を使って確認することができます。詳しくは後述します。
実行時の動作
実行時には、CO から生成されたバイトコードが Mutable の独自形式のデータを参照する形で実行されます。
Customizable Object のデバッグ機能
Mutable には、CO のデバッグ機能があります。デバッグ機能を使うことで、CO のコンパイル結果を確認できます。