実際のプロジェクトで起こる問題の多くは「ケアレスミス」によるものです。「試験的な」臨時修正や、疲れたディベロッパーがうっかりクリックしたことにより、知らないうちにパフォーマンス性の低いアセットが追加されてしまったり、既存のアセットの重要な設定が変更されてしまうことも多々あります。
ある程度規模の大きなプロジェクトでは、人的ミスに対する防衛線を張るようにしましょう。小さなコードを書くことで比較的簡単に、誰かが 4K の非圧縮テクスチャをプロジェクトに追加してしまうのを防ぐことは可能です。
しかし、それでもなお、このようなミスは驚くほど頻繁に起こっています。 4K の非圧縮テクスチャは 60 MB のメモリを占領します。 iPhone 4S などの低性能モバイル端末では、 180~200 MB 程度を超えるメモリを消費するのは危険です。このようなテクスチャをうっかり追加してしまえば、アプリケーションのメモリ予算の 3 分の 1 から 4 分の 1 が意図せず占領されることとなり、診断が困難なメモリ超過エラーが発生してしまいます。
現在では 5.3 Memory Profiler を使用してこうした問題のトラッキングを行うことが可能ですが、このようなミスが発生する可能性自体を排除するほうが明らかに賢明です。
Unity エディタの AssetPostprocessor
クラスは、 Unity プロジェクトにおいて一定の最低基準が確実に満たされるようにするために使用できます。このクラスは、アセットのインポート時にコールバックを受け取ります。これを使用するには、 AssetPostprocessor
から継承して、 OnPreprocess
メソッドを 1 つ以上実装します。以下はその主な例です。
OnPreprocessTexture
OnPreprocessModel
OnPreprocessAnimation
OnPreprocessAudio
利用可能なその他の OnPreprocess
メソッドについては、スクリプト リファレンスの AssetPostprocessor をご覧ください。
public class ReadOnlyModelPostprocessor : AssetPostprocessor {
public void OnPreprocessModel() {
ModelImporter modelImporter =
(ModelImporter)assetImporter;
if(modelImporter.isReadable) {
modelImporter.isReadable = false;
modelImporter.SaveAndReimport();
}
}
}
これは、 AssetPostprocessor
がプロジェクトに規則を設定する単純な例です。
このクラスは、プロジェクトへのモデルのインポート時と、モデルのインポート設定が変更された際に呼び出されます。コードは Read/Write enabled
フラグ( isReadable
プロパティで表される)が true
に設定されているかどうか確認します。 true
に設定されていれば、フラグを強制的に false
にしてからアセットを保存して再インポートします。
SaveAndReimport
を呼び出すと、このコード スニペットが再度呼び出されることにご注意ください。ただし、この時点で isReadable
が確実に false になっているので、このコードが再インポートの無限ループを発生させることはありません。
この変更の理由は以下の「モデル」の項で説明しています。
Read/write enabled フラグは無効にする
Read/Write enabled
フラグを有効にすると、テクスチャがメモリ内に 2 回書き込まれます。 GPU で 1 回、 CPU アドレサブル メモリで 1 回です (1) ([注]
これは、ほとんどのプラットフォームで、 GPU メモリからのリードバックが極端に遅いためです。 GPU メモリからテクスチャを一時バッファに読み込んで CPU で使用する{[例] Texture.GetPixel }のは、非常に非効率的です。)。 Unity のデフォルトではこの設定は無効になっていますが、間違って有効にしてしまうことがあります。
Read/Write Enabled
は、(Texture.GetPixel
や Texture.SetPixel
API などで)シェーダー外でテクスチャデータを操作する場合以外は必要になりません。必要な場合以外は使用を控えるようにしてください。
Mipmap は可能な限り無効にする
Z 深度がカメラに対して比較的不変であるオブジェクトに関しては、Mipmap を無効にすることで、テクスチャの読み込みに掛かるメモリの約 3 分の 1 を節約することができます。オブジェクトの Z 深度が変化する場合は、 Mipmap を無効にすると、 GPU におけるテクスチャ サンプリングのパフォーマンスが劣化することがあります。
これは基本的に、UI テクスチャなどの、画面上において一定のサイズで表示されるテクスチャに適しています。
テクスチャは全て圧縮する
メモリを節約する上では、プロジェクトのターゲット プラットフォームに適したテクスチャ圧縮方式を使用することが非常に大切です。
選択したテクスチャ圧縮形式がターゲットプラットフォームに適していないと、テクスチャが読み込まれた際、解凍のために CPU 時間と過剰な量のメモリが消費されます。この問題は Android デバイスで最も頻繁に見られます。 Android デバイスは往々にして、チップセットに応じて多種のテクスチャ圧縮形式に幅広く対応しているためです。
テクスチャサイズの妥当な上限値を設定する
これは簡単なことですが、テクスチャのリサイズを忘れたり、テクスチャ サイズのインポート設定を意図せず変えてしまうことはよくあります。テクスチャのタイプに応じて適切な最大サイズを決め、コードから強制するようにしてください。
多くのモバイルアプリケーションの場合、テクスチャ アトラスには 2048x2048 あるいは 1024x1024、 3D モデルに適用されるテクスチャには 512x512 で十分です。
Read/Write enabled フラグは無効にする
モデルの Read/Write enabled
フラグも、上述のテクスチャの場合と全く同様に機能します。ただし、モデルの場合はこれがデフォルトで有効になっています。
このフラグは、スクリプト経由でランタイムでメッシュを修正する場合や、メッシュが MeshCollider コンポーネントの基盤として使用される場合には有効になっている必要があります。モデルが MeshCollider 内で使用されておらず、スクリプトによって操作されていない場合は、そのモデルのメモリを半分に節約するためにこのフラグは無効にしてください。
非キャラクターモデルのリグは無効にする
Unity のデフォルトでは、非キャラクターモデルには汎用リグがインポートされます。これは、モデルがランタイムでインスタンス化された場合に Animator
コンポーネントを 1 つ追加します。モデルがアニメーションシステムによってアニメーション化されていない場合は、このためにアニメーションシステムに不要なオーバーヘッドが追加されることになります。なぜなら、アクティブな Animator は全て 1 フレーム毎に 1 回チェックされる必要があるからです。
このように Animator コンポーネントが自動的に追加されてしまったり、不要な Animator がミスによってシーンに追加されてしまうのを防ぐために、アニメーションではないモデルのリグは無効にしてください。
アニメーションモデルの Optimize Game Objects オプションを有効にする
Optimize Game Objects オプションは、アニメーションモデルのパフォーマンスに大きく影響を及します。このオプションが無効になっている場合、 Unity は、モデルがインスタンス化されるたびに、そのモデルのボーン構造をミラー (反転) する大きな Transform ヒエラルキーを作成します。この Transform ヒエラルキーの更新には高い負荷が掛かります。特に、(Particle System や Collider などの)別のコンポーネントが添付されている場合はなおさらです。またこれにより、Unity の、メッシュ スキニングやボーンアニメーション計算をマルチスレッド処理する能力に制限が掛かります。
モデルのボーン構造の特定箇所をアクセス可能にする必要がある場合([例]武器モデルを動的に添付するためにモデルの手をアクセス可能にする場合など)は、そういった箇所は Extra Transforms
リスト内で明示的に登録することが可能です。
Unity マニュアルの モデルインポーターに関するページで、さらに詳細情報をご覧いただけます。
可能な限りメッシュ圧縮を使用する
メッシュ圧縮を有効にすると、モデルのデータの各チャンネルの浮動小数点数を表すのに使用されるビット数が削減されます。これにより精度が若干低下することがあります。最終版プロジェクトで使用する前に、アーティストがこの精度低下の影響をチェックする必要があります。
特定の圧縮レベルで使用される具体的なビット数は、スクリプト レファレンスの ModelImporterMeshCompression のページでご確認いただけます。
チャンネルごとに異なるレベルの圧縮を使用することも可能です。したがって、例えば同一プロジェクトでタンジェントと法線だけ圧縮し、 UV と頂点位置は非圧縮のままにするということもできます。
(注) Mesh Renderer Settings
Mesh Renderer をプレハブやゲームオブジェクトに追加する際は、コンポーネントの設定に注意が必要です。 Unity のデフォルトでは、 Cast Shadows(影の投影)、Receive Shadows(影の表示)、 Light Probe のサンプリング、 Reflection Probe のサンプリング、 Motion Vector の計算が有効になっています。
こうした機能を一つも必要としないプロジェクトの場合は、スクリプトによってこれらが自動的にオフになるようにしてください。また MeshRenderers を追加するランタイムコードも全て、これらの設定を切り替える必要があります。
2D ゲームでは、シャドウのオプションがオンになった MeshRenderer が間違ってシーンに追加されると、レンダリングループに完全なシャドウパスが追加されてしまいます。これは基本的にパフォーマンスの浪費です。
プラットフォームに適した圧縮設定
対応ハードウェアに適したオーディオ圧縮形式を有効にしてください。全ての iOS デバイスにはハードウェア MP3 解凍装置が搭載されており、 Android デバイスの多くは Vorbis にネイティブ対応しています。
さらに、非圧縮オーディオファイルを Unity にインポートしてください。プロジェクトがビルドされる際は毎回 Unity によってオーディオが再圧縮されます。圧縮オーディオをインポートしてからそれを再圧縮する必要はありません。そのようにするとオーディオの最終品質が低下してしまいます。
オーディオクリップを強制的に Mono にする
ステレオスピーカーを搭載したモバイルデバイスは少数です。モバイルプロジェクトの場合は、インポートされたオーディオクリップを強制的にモノチャンネルにすることで、その消費メモリが半分に削減できます。この設定は、 UI サウンドエフェクトなどの、ステレオエフェクトのないオーディオ全てに適用できます。
オーディオのビットレートを低くする
これはオーディオデザイナーと相談しながら行う必要がありますが、メモリ消費量やビルドされたプロジェクトのサイズを抑えるために、オーディオファイルのビットレートは可能な限り低くしてください。
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.