事前構築の利用

概要


クロスシミュレーションを行うには様々なデータが必要となります。
これらはクロスデータと呼ばれ、設定されたメッシュやパラメータから生成されます。
MagicaClothではこのクロスデータを生成する作業を構築(Build)と呼んでいます。

これまでMagicaCloth2では実行時構築のみが利用可能でした。
実行時構築(Runtime Build)ではクロスデータは利用時にその場で作成されます。
このクロスデータの作成には数ms~数十msの時間がかかります。
この構築作業はバックグラウンドで行われるためゲーム進行には影響はありませんが、実際にシミュレーションが開始されるまでに遅延が発生することになります。
これが実行時構築の欠点でした。

事前構築(Pre-Build)ではクロスデータを編集時に作成してアセットとして保存します。
これにより実行時には遅延なく即座にシミュレーションが開始可能です。
また、初期化の負荷も下がるためパフォーマンスの面でも有用です。
ただし、編集時に構築作業が必要になることと、クロスデータのアセットを別途管理する必要があるなど短所も存在します。

ここではこの事前構築の利用方法について解説します。

構築作業の比較


実行時構築と事前構築の比較は次のようになります。
どちらにもメリットとデメリットが存在します。

実行時構築
(Runtime build)
事前構築
(Pre-Build)
メリット MagicaClothのバージョン変更やメッシュやボーンの構造に変化があっても影響が無い。
パラメータが変更されても特別な操作は必要無い。
初期化の負荷が低い。
シミュレーションは即座に開始される。
初期化時のキャラクターのポーズとスケールはどのような状態でも良い。
デメリット クロスデータ構築のため初期化の負荷が高い。
データ構築に時間が掛るためシミュレーションが開始されるまでに遅延が発生する。
キャラクターは編集時と同じポーズとスケールで初期化しなければならない。
クロスデータを作成するための操作が必要。
MagicaClothのバージョン変更やメッシュやボーンの構造変化により容易にクロスデータが利用できなくなる。
パラメータが変更されるたびにクロスデータを再構築する必要がある。

事前構築の方法


インスペクターパネル

事前構築はMagicaClothコンポーネントの一番下にある[Pre-Build]パネルから設定します。
まずこのパネルを有効にしてください。

ビルドID

最初にクロスデータに任意の識別用のIDを付ける必要があります。
これをビルドIDと呼びます。
コンポーネント作成時には英数8文字のランダムな文字列が割り当てられていますが、なるべくわかりやすい名前に書き換えたほうが良いでしょう。
例えばスカートのMeshClothならばIDを”skirt”などに変更します。

クロスデータの作成と保存

“Create PreBuild Data”ボタンを押すことでクロスデータの作成が開始されます。
すべてのパラメータのセットアップが完了していることが必要です。
“Write Object”が空の場合はアセットの保存ダイアログが表示されます。
任意の名前を付けてアセットを保存してください。

正常にクロスデータが保存されると状態が”Success”に変化します。
そして”Write Object”に保存したアセットがリンクされます。
次のような状態であれば成功です。

クロスデータはMagicaClothコンポーネントとは異なる別のアセットとしてファイル保存されます。
これらはProjectウインドウで確認することができます。

実行する

それでは実行してみましょう!
設定が済めば後はプレイボタンを押すだけです。
実行時構築と違いシミュレーションは即座に開始されます。
それ以外はこれまでの実行時構築とまったく同じです。

状態の確認

事前構築が利用されているかどうかは、実行中のMagicaClothコンポーネントのインスペクターから確認できます。
次のように情報パネルに”Pre-Build Construction”が表示され、状態が”Success”になっていれば正常に動作しています。

クロスデータの脆弱性

事前構築のデータ作成自体はボタンを押すだけで完了する簡単なものですが大きな注意点があります。
それはリソースの変更にとても弱く容易にデータが使えなくなってしまうことです。
例えばクロスデータ内部のメッシュ頂点数と実際のメッシュの頂点数が合わなくなった場合などが該当します。

そのため次の要因が発生した場合は構築をやり直す必要があります。

  • パラメータが変更された場合
  • 参照するメッシュの構造が変更された場合
  • 参照するTransformの構造が変更された場合

既存のクロスデータに追加する

事前構築のクロスデータは1つのアセットに複数保存することも可能です。
この場合は次のようにします。
まず、構築する前に”Write Object”として既存のクロスデータアセットを選択しておきます。

この状態で事前構築を実行することで、指定アセットにクロスデータが追加されます。

実際にProjectウインドウでクロスデータアセットを選択すると、次のように複数のクロスデータが保存されていることが確認できます。

キャラクターに複数のMagicaClothが設定されている場合は、すべてをまとめて1つのクロスデータアセットとして管理することも可能です。

クロスデータアセット


保存されたクロスデータアセットはProjectウインドウから選択することで内容を確認することができます。

状態

インスペクターにはクロスデータのビルドIDと状態が表示されます。
状態が”Success”の場合は問題ありません。
それ以外の場合はエラーが発生しており、クロスデータが利用できない状態となります。

削除

すでに不要となったクロスデータはリストから自由に削除可能です。
また、クロスデータアセットそのものが不要な場合はProjectウインドウからアセットを削除してください。

手動作成

クロスデータアセットは手動で作成することも可能です。
次のようにProjectウインドウで右クリックメニューを開き、Create/MagicaCloth2/PreBuildScriptableObjectを選択することで作成可能です。

高度な操作


ここでは主にプログラマに向けたデータの管理方法について解説します。
これらの操作はオプションとなるため必須ではありません。

ウォームアップ

事前構築のクロスデータは基本的にバイトデータの集まりです。
実行時にクロスデータが利用されるときには、このバイトデータから元のデータ構造に復元するデシリアライズ処理が行われます。
このデシリアライズは比較的負荷が高い処理となります。

もしこの負荷が問題となる場合はクロスデータを前もってデシリアライズさせておくことができます。
一度デシリアライズされたデータは常駐され、再度デシリアライズされることはありません。
これはPreBuildScriptableObjectに対して次のAPIを実行することで行われます。

/// <summary>
/// すべてのPreBuildデータをデシリアライズしてマネージャに登録します
/// この処理は負荷が高いため事前に実行しておくことでクロスデータ利用時の負荷を軽減できます
/// Deserialize all PreBuild data and register it with the manager.
/// This process requires a high load, so running it in advance can reduce the load when using cross data.
/// </summary>
public void Warmup();

クリーンアップ

デシリアライズされたクロスデータはメモリに常駐します。
常駐データは利用カウンタにより管理されますが、利用カウントが0になっても自動的には解放されません。
これは頻繁に生成と削除を繰り返すキャラクターなどでの利用を想定したものです。
常駐データはそれほど大きなものではありませんが、未使用のデータがメモリに残り続けることになります。

これを解決するためにクリーンアップの機能が用意されています。
クリーンアップを実行することで、利用カウントが0の常駐データがすべて解放されます。
これにはMagicaManagerの次のAPIを利用します。

/// <summary>
/// 未使用のデータをすべて解放します
/// Free all unused data.
/// - Unused PreBuild data
/// </summary>
public static void UnloadUnusedData();

この実装はUnityの未使用アセットを解放するUnloadUnusedAssets()とほぼ同じです。

スクリプトからの実行

事前構築はスクリプトから実行することも可能です。
これにはPreBuildDataCreationクラスのCreatePreBuildData()を利用します。
ただし、事前にビルドIDと保存先クロスデータアセットが設定されている必要があります。

/// <summary>
/// PreBuildDataを作成しアセットとして保存する
/// Create PreBuildData and save it as an asset.
/// </summary>
/// <param name="cloth"></param>
/// <param name="useNewSaveDialog"></param>
/// <returns></returns>
public static ResultCode CreatePreBuildData(MagicaCloth cloth, bool useNewSaveDialog = true);