デフォルトメモリプール(Default memory pool)には、メモリにロードされた各種サウンドやイベントに関連する、構造的なメタデータが入っています。Wwiseで定義した動作を実行するために必要な、オブジェクトのプロパティが、全て入っています。また、登録されている全てのゲームオブジェクトと、それらに関連したゲームシンク値、ポジション、向き(Orientation)などの情報も含まれます。メモリにロードされるバンク数が増えると、メタデータも追加されるので、必要なデフォルトメモリプールのサイズが大きくなります。必要なメモリサイズを最終的に決めるのは、1つのシナリオ、レベル、マップ、またはゲーム領域などで再生される可能性のあるサウンドの、最大数です。
注釈 | |
---|---|
デフォルトメモリプールに、メディアは一切入りません。 |
サウンド構造やイベントの組み合わせは、それぞれ、デフォルトメモリプールのメモリを平均で約300バイト使います。例えば、プロジェクトにあるサウンドが(ダイアログも含め)50,000個以上でれば、構造データだけでも、約15MBのメモリが必要です。明らかに、全てを同時にメモリにロードすることはできないので、構造データもメディアと同様に、ロードしたりアンロードしたりする必要があります。
これまでの数々のWwiseプロジェクトを参考にすると、デフォルトメモリプールに占める割合が最も高いのが、サウンド構造(25〜50%程度)で、メモリにロードする個数があまりにも多いためです。もちろん、ロードするサウンド数が少なければ、デフォルトメモリプールも小さくできます。次にメモリ消費が高いのがイベントのメタデータで、プール全体の約10%を占めます。イベントは非常に小さいので、数が多くてもあまり場所をとりません。単体でメモリ消費が最も高いのが、おそらくRandom ContainerやSequence Containerで、単純なサウンドと比べ、メモリ消費が3倍にいなります。しかし一般的に、サウンドやイベントよりもRandom ContainerやSequence Containerの数がかなり少ないので、合算しても、メモリプールに占めるコンテナの割合は低いです。
基本的な考え方として、オープンワールドゲームは、すぐに再生できるように待機させるサウンドが多いため、必要メモリが大きくなる傾向があります。このようなゲームでは、デフォルトメモリプールが5〜8MBほど必要です。これに比べて、他の種類のゲームのメモリ消費はかなり低く、例えば2〜3MBほどです。なお、これらの数値は、Wwiseを使った数々のゲームが今まで必要としたメモリの情報を、参考として提供するものであって、Wwiseでデザインするゲームが、このメモリ容量に収まることを保証するものではありません。
デフォルトメモリプールのメモリ消費を削減するためのベストプラクティスを、以下に示します。
多数のサウンド構造やイベントを入れた大きいバンクは、いくつかの小さいバンクに分割すること。必要に応じて、バンクをロードしたりアンロードしたりします。バンクはキャラクター別に分けるだけでなく、必ず状況別の分割も行います。
APIの、ExecuteActionOnEventを使って、イベント数を減らすこと。「Play/Stop」イベントの代わりに、Playイベント1つと、StopするためのExecuteActionOnEventの呼び出し1つに、置き換えます。同じPlayイベントの「Pause/Resume」も同様です。
ゲームオブジェクトを細かく管理すること。役割が終わったものは、すぐに登録を解除します。全くメリットがない上に、メモリを消費してしまうので、使用しないゲームオブジェクトのプールを生かしたままにしないでください。例えば、NPCが死んだ場合は、そのゲームオブジェクトの登録を解除すること。他の目的で再利用しないでください。必要となった時点で、新しいゲームオブジェクトを登録します。基本的な考え方として、数千個のゲームオブジェクトが生きている状態は、多すぎると言えます。
サウンドの整理には、仮想フォルダを使い、アクターミキサーを使わないこと。仮想フォルダはメモリを消費しませんが、アクターミキサーは消費します。アクターミキサーは、デフォルトプロパティ以外の、他のプロパティも似た複数オブジェクトに限り、使います。アクターミキサーを使うと、プロパティが似ていれば、1回出てくるだけなので、メモリを節約できます。もちろん、アクターミキサーが、Set Voice VolumeやSet Voice Pitchなどのイベントにレファレンスされるかどうかにも、よります。
大きい階層は、サイズや複雑性を減らすように努力すること。よくある大きい階層として、「Impact(衝撃)」階層や、「Footstep(足音)」階層などがあります。これらは変数が多いため、大きくなりがちで、残念ながら分割できません(メディアは分割できますが、構造データは分割できません)。このような階層を小さくする方法を、以下にいくつか示します。
変化するのが、単純なプロパティであれば、RTPCを使います(サンプルは同じで、ボリューム、ピッチ、Randomizerなどが変わる場合)。
Switch階層の複数のレベルの一部(または全て)を、同等のStateやState Group(State Group)が設定されたダイアログイベントに置き換えられます。頻繁に変わる変数に使うと、便利です。例えば、「Impact」階層では、衝撃を受ける素材を事前に既定できず、イベントが発生した時に、分かるだけです。Switch値を保持しなければならないSwitch Containerの代わりに、同じ値のStateやState Groupを設定したダイアログイベントを使えます。ダイアログイベントは、同じサンプルやサブ構造を簡単に再利用できるのが、メリットの1つです。また、ダイアログイベントでは、ゲームオブジェクトごとにはメモリを使いません。StateやState GroupパスをSwitch Containerにリンクして、変数値のレベルをさらに増やすこともできます。
例えば、「Footseps(足音)」にこの方法を活用できます。StateやState GroupパスをSwitch Containerにリンクして、変数値のレベルをさらに増やすこともできます。この仕組みの基にあるのは、ゲームオブジェクトの寿命中に「Footwear」はあまり変わらず、他の2つの変数値はよく変わるという論理です。
この方法のもう1つのメリットは、ダイアログイベントを、ダイアログイベントで再生される関連サウンド構造が入っていない、イベントだけのSoundBankに入れられることです。つまり、そのイベントに関連した、複雑な各種サウンド構造を、ほかの複数のSoundBankに分割できるのです。例えば、「Footsteps(足音)」の例では、「BankEvent」の中に、足音のDialogue Eventを入れ、「Concrete(コンクリート)」関連の構造やメディアを「BankConcrete」に入れ、「Dirt(泥)」関連の構造やメディアを「BankDirt」に入れます。使用方法としては、新たな地面の種類に接近する時に、SoundBankをダイナミックにロードしたりアンロードしたるするだけです。
Switch Container階層を、複数のSoundBankに分けることができます。SoundBankにSwitch Containerを追加する時に、コンテナのサブブランチも全て、自動的に含まれます。ただし、SoundBank Editorの、Game Syncsタブや、Editタブで、マニュアル操作で一部のサブブランチを除外することもできます。例えば、「Footstep」階層の最上位にあるSwitch変数が、地面の種類だとします。ゲーム中に、常に全種類の地面を待機させる必要がなければ、Switch Containerの階層を複数のSoundBankに分割して、ゲームの状況に応じて、必要な地面の種類だけをロードすることができます。そこで、例えば「Concrete(コンクリート)」や「Metal Stairs(鉄骨階段)」など、ゲーム中にどこにでも出現するような地面の種類をメインバンク「Footstep」に入れて、「Mud(泥)」など、出現するシーンや場所が限定される地面に関しては、状況別に分けたほかのSoundBankに入れることができます。
ある衝撃サウンドのバリエーションをつくり出すために、.wavファイルをいくつも準備するのではなく、SoundSeed Impactの同等サウンド1つで対応できます。例えば「ガチャン」という音を10種類も用意せずに1つのサウンドで置き換えれば、経済的なだけでなく、バリエーションが10種類よりも多くなります。この手法を使うと大きな差が出るので、見落とさないでください。