メモリ使用量を最適化する

ゲームを実行するには、プロジェクトのリソースをメモリにロードしてレンダリングするか、そこに格納されているデータを操作する必要があります。また、ゲームを実行できるデバイスごとに、ゲームで利用可能なメモリ容量に関する厳しい制限があります。これにより、ゲームが特定の時間内にロードできるリソースの数とサイズが両方制限されます。言うまでもなく、モバイル デバイスではこれらの上限が低くなっています。ただし、ゲーム プロジェクトの対象範囲が広がるにつれて、64 ビット PC およびコンソールでもメモリがますます貴重になっています。

ゲームがメモリ不足にならないようにすることが重要です。ゲームに必要なメモリ容量がオペレーティング システムから取得できる容量を超えている場合は、エンジンが対応するチャンスを得る前に、オペレーティング システムによって即座にゲームがクラッシュして終了する可能性があります。

ゲームの負担が大きくなってクラッシュするまで、メモリ使用量を無視することはしないでください。代わりに、より事前対策的なアプローチを使用してプロジェクトの開始時点から予算およびベスト プラクティスを確立し、開発サイクル全体で実際の使用量を監視します。こうすることにより、リリース前の最終段階でパニックにならずに済みます。

このページには、ゲームに必要なメモリ サイズを削減するためのヒントおよび技術がいくつか示されています。これらは、次の 3 つのカテゴリに分類されます。

予算または見積もりを設定する

メモリ使用量を最適化および最小化する前に、達成しようとしている目標を明確にしておくと役立ちます。

全体的な予算は、ユーザがサポートするハードウェア デバイスの仕様に応じて変わります。ここから、オペレーティング システムで使用するメモリを差し引く必要があります。次に、他のアプリで使用されるメモリ容量に対応する、大きな割合を差し引きます。ゲームがデバイスで実行されている唯一のアプリであると想定することはできません。最後に、「上限」に少し余裕を持たせるために、さらに追加の割合を差し引きます。予測できないクラッシュからの保護方法に応じて、全体的な目標値はデバイスの利用可能メモリ サイズの 4 分の 1 またはそれ以下になることがあります。

ゲームの全体的な予算を総体的に把握できたら、予算全体をサブシステムごと、または種類のリソース(テクスチャ、オーディオ、メッシュなど)ごとに小さな予算に分割すると便利です。ここに示した値は、開発するゲームの種類に応じて異なる可能性があります。たとえば、ゲームの鑑賞性を高める目的で意図的に低品質のポリゴン アートを使用し、複雑な音楽やオーディオ キューを含める必要がある場合、ビジュアル重視のゲームよりも予算全体に対して大きな割合の予算をオーディオ リソースに割り当てなければならないことがあります。これらの予算を絶対的なルールにする必要はありません。プロジェクトを通して交渉によって定めることができます。ただし、複数のチーム メンバーがプロジェクトのさまざまな領域で作業している場合は、大まかな予測値を事前に設定しておくと、チーム内のコラボレーションをさらに円滑にすることができます。

ランタイムの使用量を監視する

ランタイムでゲームが実際に使用するメモリ容量に関する明確なデータが存在しない場合は、解決しなければならない問題の領域を特定できなくなります。データがなければ、間違った領域に時間と労力を費やしてしますことがあります。たとえば、実際は巨大で極めて詳細なモデルが問題の引き金となっている場合でも、テクスチャ品質を積極的に下げてしまうことがあります。

ランタイムでゲームで使用されるメモリを評価することも重要です。なぜなら、リソースのメモリ サイズは、ディスク上のリソースのサイズと大幅に異なることがあるためです。たとえば、プロジェクト フォルダ内のイメージ テクスチャは圧縮された .png 形式でディスクに格納されていることが多いため、ディスク上のサイズが小さくなることがあります。ところが、ランタイムのメモリではテクスチャ データが圧縮解除されて、ファイル サイズから予測される値よりもはるかに多くの容量を使用します。

ゲーム内のメモリ使用量に関する情報を取得するためのコンソール コマンドがいくつかあります。

Stingray エディタから実行時のゲームにコマンドを送信する方法の詳細については、「ステータス バーからコマンドを送信する」を参照してください。コマンド自体の詳細については、「コンソール コマンド」を参照してください。

ブート パッケージまたはプロジェクトから未使用のリソースを除去する

起動時にゲームがクラッシュする場合、特に利用可能メモリが少ないモバイル デバイスでテストする場合に最も可能性の高い原因は、ブート パッケージが極端に多くのリソースをロードしようとしていることです。

ブート パッケージがそれに含めるリソースを決定するためにワイルドカードを使用している場合は、ロードされるリソースの一部が実際には必要でない可能性もあります。次のような行を記述することによってプロジェクト内のすべてのタイプのすべてのリソースをロードしている場合は、特にその可能性が高くなります。

* = ["*"]

ワイルドカードと一致するものの、ランタイムには必要とされないアセットの古いコピーやテスト レベルがプロジェクトに多数ロードされている場合は、プロジェクトからそのような不要なリソースを削除することにより、メモリを節約できます。

または、古いコピーを保持しておきたい場合は、ブート パッケージから自動ローディングの行を除去し、不要なリソースを除外するようにブート パッケージを再設定することもできます。

ブート パッケージについて」および「リソース パッケージを定義する」も参照してください。

複数のリソース パッケージを使用する

ゲームのメモリ使用量をコントロールするために用意されている最も強力かつ柔軟なオプションは、パッケージのリソースを複数の独立したパッケージに分割し、必要に応じて、ゲーム中にこれらのパッケージをメモリに動的に出し入れすることです。

異なる時点でさまざまなリソース セットが必要になるプロジェクトでは、一般にこの方法を利用できます。たとえば、ゲームに複数のレベルがある場合は、各レベルで使用されるアセットごとに独立したリソース パッケージを作成できます。このようにすると、各レベルは、利用可能なメモリを他のレベルと共有しなくても、ゲームのメモリ予算全体を使用することができます。レベルが 1 つしかない場合も、そのレベルの独立した複数のパーツ、複数のキャラクタなどにリソース パッケージを使用できる可能性があります。

この種類のシステムを設定する方法の詳細については、「ランタイムでコンテンツをロードおよびロード解除する」のトピックを参照してください。

リソース パッケージをメモリに出し入れするためのカスタム システムを設定する場合も、次に示す他の技術を適用して、ロードする個々のリソースを最適化することができます。

テクスチャを最適化する

これまで、ほとんどのゲームでメモリを最も多く使用してきたのはテクスチャです。もちろん、ゲームのビジュアルを魅力的にする上で、テクスチャは大きな役割を果たしています。したがって、ビジュアル面の品質とメモリ サイズの適切なバランスを取るのは困難なことがあります。画面サイズや利用可能メモリが大きく異なる複数のプラットフォームをサポートする必要がある場合は、特にそうです。画面が大きいデバイスでは、イメージ品質を重視しなければならない可能性があります。逆に小さい画面では、品質を下げて小さなテクスチャを使用しても、レンダリング品質にはっきりとした違いは生じません。

次のセクションでは、プロジェクトのメモリと品質のバランスを最適化するのに役立つヒントをいくつか示します。

テクスチャ サイズを小さくする

テクスチャを最適化するには、まず、適切なイメージ サイズを判別します。ゲーム内のすべてのテクスチャのサイズを 4096x4096 ピクセルにすると、すべてのシステムですぐにメモリ不足になります。

テクスチャの適正サイズに関する明確なルールは存在しません。最終的には、次の条件に応じて判断します。

また、各マテリアルに割り当てるテクスチャ マップごとに異なるサイズを使用して、実験することもできます。たとえば、粗いマップやメタル質のマップにカラー マップや法線マップよりも小さなイメージを使用しても、通常は、レンダリング時のマテリアルの表示方法で品質が目に見えて低下することはありません。

圧縮テクスチャのストリーミングに対しては、ピクセル サイズを 4 の倍数にする必要があります。

プラットフォーム単位のコンパイル設定を使用する

Stingray の Texture Manager を使用して、ターゲット プラットフォームごとに Stingray でのテクスチャのコンパイル方法をコントロールすることができます。

Texture Manager の使用法の詳細については、「テクスチャを使用する」を参照してください。

テクスチャ ストリーミングを利用する

既定により、Stingray は他のすべてのリソースと同様にテクスチャを処理します。テクスチャはリソース パッケージ内の他のすべてのリソースとともにメモリにロードされ、メモリに永続的に保管されます。ロード解除されるのは、リソース パッケージがロード解除されるときのみです。つまり、テクスチャが画面外にある、または非常に遠くにあるために各テクスチャのミップ レベルが実際は使用されていない場合でも、各テクスチャのすべてのミップ レベルがゲーム内のメモリを使用しています。

テクスチャ データが実際にレンダリングに必要な場合に限ってこれらのデータをメモリにストリーミングするように、Stingray を設定することができます。テクスチャ ストリーミングを使用すると、ゲーム内で使用するテクスチャのメモリ使用量を増やしたり、最大解像度を小さくしたりしなくても、これのテクスチャの数を増やすことができます。

このシステムの仕組みの詳細については、「テクスチャ ストリーミング」を参照してください。

テクスチャ ストリーミングのメモリを小さくする

エンジンは、テクスチャ ストリーミング システムが使用するための 16 MB のメモリを起動時に予約します。ゲーム内でテクスチャ ストリーミングを使用しない場合は、ターゲット プラットフォームごとにプロジェクトの settings.ini ファイル内の streaming_buffer_size キーを 0 に設定して、このメモリの割り当てを回避することができます。「Stingray エンジンの settings.ini ファイルのリファレンス」を参照してください。

ライトマップ テクスチャ サイズを小さくする

レベルのライティングをベイク処理するときに、ゲーム中にロードする必要がある追加のテクスチャが生成されます。一般に、ベイク処理を行うと、CPU および GPU の使用率を下げても高品質のレンダリングを実現できるようになりますが、ランタイムのメモリ要件が厳しくなるという代償が常に伴います。

ライトマップがメモリを使用しすぎる場合は、次のアイデアを試すことができます。

モデルを最適化する

プロジェクトに追加する各モデル アセット内の頂点数およびデータ チャネル数が多いほど、ゲームにこのメッシュをロードするのに使用されるメモリ容量が増えます。モデリング ツール(3ds Max や Maya など)でメッシュを最適化して、頂点数を減らしたり、ゲームに不要なすべてのチャネル(余分な UV セットなど)を除去したりして、メモリの一部を節約することができる可能性があります。

目標とすべき頂点数に関する厳しいルールはありません。テクスチャ サイズの場合と同じように、ゲーム内でレンダリングするときにモデルのビジュアル面の品質とメモリ要件のバランスを取る必要があります。モデルのビジュアル面の品質は、モデルのサイズ、カメラからの距離、およびゲームプレイやシーンに対する重要性によって決まります。モデルによっては、映画セットの装飾のように処理できる場合があります。プレイヤーに特定の建物またはオブジェクトの背面が見えない場合は、頂点数が最小のフラットな平面にすることができます。

メッシュ サイズが大きすぎて処理を開始できない場合を除き、テクスチャを最適化した場合のようにメモリ消費量に大きな違いが生じることはない可能性があります。ただし、ゲーム内に同時に存在するメッシュが増えるほど、わずかな最適化で大きな成果が得られます。

オーディオを最適化する

テクスチャおよびメッシュの次にゲーム内でメモリ使用量が最大となることが多いリソース タイプは、オーディオ ファイルです。

上記のテクスチャやメッシュと同様に、サウンド品質とのトレードオフによってメモリ要件を緩和することができます。ただし、ディスクからオーディオを直接ストリーミングする、Wwise エンジンで内部的に割り当てられるメモリ プール サイズを調整するなど、追加で使用できる他の補足技術が多数存在します。

詳細については、「オーディオのメモリ使用量を最適化する」を参照してください。

物理的特性を最適化する

物理的なサブシステム内で実行できる主なメモリ最適化は、アクターおよびムービーが不要なすべてのユニットでアクターおよびムービーを作成しないことです。ユニットをスポーンすると、いつでも、アクターおよびムービー用の追加容量がメモリ内に予約されます。

アニメーション クリップを圧縮する

Asset Browser でアニメーション クリップを選択すると、Property Editor に、コンパイル時にこのクリップに適用できる一連の圧縮設定が表示されます。これらの圧縮設定を有効にすると、ランタイムでメモリの一部を節約できますが、アニメーション カーブが少し不正確になります。

各クリップの圧縮設定を微調整するには、位置、回転、またはスケール カーブの圧縮を個別に有効および無効にするとともに、許容値を調整してデータ圧縮のアグレッシブさと許容されるエラーの大きさとの間のバランスをコントロールします。

詳細については、「アニメーション クリップのプロパティ」、「 アニメーションの圧縮」および「アニメーションの最適化」も参照してください。

Lua 環境およびスクリプトを最適化する

Lua 環境で使用されるメモリ量を低く抑えるには:

Lua メモリの問題に関するこのブログの投稿も参照してください。

レベル設計およびゲームプレイでリークを確認する

上記のオプションを実行してゲーム内に各種のリソース タイプおよびサブシステムで消費されるメモリを削減した後も、レベルで使用されるメモリ容量が多すぎる場合は、レベルが不必要にメモリを消費していないか、または知らないうちにメモリを消費していないか徹底的に確認してください。