
「Unityモバイルゲームパフォーマンス最適化略譜」は、Unity モバイル ゲームの最適化に関するいくつかの基本的な議論から始まり、近年 Unity に基づいて開発されたモバイル ゲーム プロジェクトで最も一般的なパフォーマンスの問題のいくつかを例示および分析し、さらにUWA のパフォーマンステストツールを使用してこれらの問題を特定して解決する方法を示します。このコンテンツには、パフォーマンス最適化の基本的なロジック、UWA パフォーマンステストツール、および一般的なパフォーマンスの問題が含まれており、Unity 開発者により効率的な開発方法と実践的な経験を提供することを望んでいます。
今日は記事の第 2 部分として、リソース メモリ、Mono メモリなどの一般的なゲーム メモリ コントロールを紹介します。主にテクスチャ、メッシュ、アニメーション、オーディオ、マテリアルなどのリソース メモリとMono メモリおよびその他の一般的なゲーム メモリ コントロールの説明なども含まれています。合計 13 のセクションがあります。
(全文は約17,900字、読むのは約20分かかります)
第一部分はここに移動してご覧ください。
1.総覧
1.1 概念説明
まず、メモリに関連するさまざまなパラメータと策定標準を説明する前に、さまざまなパフォーマンス ツールの統計データによく現れる各種メモリ パラメータの実際の意味を明らかにする必要があります。
Android システムで最も一般的に見られ、気にされる PSS (Proportal Set Size) メモリは、RAM 内のプロセスによって実際に使用される空間アドレスのサイズ、つまり実際に使用される物理メモリのサイズです。結果から見れば、ゲーム プロセスの PSS メモリ ピークが高ければ高くほど、現在のハードウェアの合計物理メモリの割合が高くなります。ゲーム プロセスがシステムによって強制終了 (フラッシュバック) される可能性が高くなります。
PSS メモリでは、Unused部分の以外、Reserved Totalメモリ、Lua 、Native コード、プラグインなどのシステム キャッシュ、およびサードパーティ ライブラリの自身割り当てを一般的に考慮します。 Reserved Total の割合は一般的に高いため、そのサイズと傾向は、UWA パフォーマンス分析ツールの主要な統計対象でもあります (Lua を使用するプロジェクトの場合、UWA は Lua 特別なテスト レポートも提供して、Lua メモリをカウントします。これについては後述します)。
Reserved Total と Used Total は、メモリに関する Unity エンジンの全体的な割り当てと全体的な使用量です。一般的に言えば、エンジンがメモリを割り当てるとき、オペレーティング システムから出してすぐに使えるのではなく、最初に一定量の連続したメモリを取得し、それを内部で使用するために使用します。空きメモリが不十分な場合、エンジンはシステムにもう一度一定量の連続したメモリを申請して使用します。
注: ほとんどのプラットフォームでは、Reserved Totalメモリ = Reserved Unityメモリ + GFX メモリ + FMOD メモリ + Mono メモリ
(1) Reserved Unityメモリ
Reserved Unity と Used Unity は、各 Manager のメモリ使用量、シリアル化された情報のメモリ使用量、一部のリソースのメモリ使用量など、Unity エンジンの各モジュール内に割り当てられたメモリです。
多数のプロジェクトを詳細に分析した結果、UWA は、Reserved Unity の割当メモりが多すぎる原因は次のとおりであることを発見しました。
シリアル化された情報のメモリ使用量: Unity エンジンのシリアル化された情報には多くの種類があり、その中で最もメモリ使用量が多いのは SerializedFile です。シリアル化された情報のメモリ割り当ては、主にプロジェクトが特定の API (WWW.LoadFromCacheOrDownload、CreateFromFile など) を介して AssetBundle ファイルをロードすることによって発生します。
リソースのメモリ使用量: 主に Mesh、AnimationClip、RenderTexture などのリソースが含まれます。 「Read/Write Enable」オプションがオンになっていないメッシュの場合、メモリ使用量は GPU 用の GFX メモリでカウントされますが、このオプションをオンにすると、メッシュ データは Reserved Unity に保留され、プロジェクト実行中でメッシュ データのリアルタイム編集と修正のに便利です。同時に、開発 チームがテクスチャ の “Read/Write Enable” オプションもオン (デフォルトではオフ) にすると、テクスチャも Reserved Unity で保留されるため、もっと大きなメモリ使用になってしまいます。
(2)GFXメモリ
GFX メモリは、基になるグラフィック カード ドライバーによってフィードバックされるメモリ割り当て量であり、基になるグラフィック カード ドライバーによって制御されます。一般的に言えば、この部分のメモリ使用量は、主にテクスチャ リソース、メッシュ リソース、GPU に送信される Shader リソースの一部、及びこれらのリソースを解析する関連ライブラリによって割り当てられるメモリなど、レンダリング関連のリソース量によって決まります。
(3) マネージヒープメモリ
マネージド ヒープ メモリは、プロジェクトのランタイム コードによって割り当てられたマネージド ヒープ メモリの割り当て量を表します。コードのコンパイルに Mono を使用するプロジェクトの場合、マネージド ヒープ メモリは主に Mono によって割り当てられ、管理されます。コードのコンパイルに IL2CPP を使用するプロジェクトの場合、マネージド ヒープ メモリは主に Unity 自体によって割り当てられ、管理されます。
1.2 メモリパラメータ規格
メモリに関連するさまざまなパラメーターの意味を理解すると、ゲームのクラッシュを回避するための鍵は PSS メモリのピークを制御することであることがわかります。 PSS メモリの大部分は、Reserved Totalのリソース メモリとモノ ヒープ メモリにあります。 Lua を使用するプロジェクトの場合、Lua メモリも考慮する必要があります。
UWA の経験によると、PSS メモリのピークがハードウェア メモリの合計の 0.5 ~ 0.6 倍未満に制御されている場合にのみ、フラッシュバックのリスクは低くなります。たとえば、2GB デバイスの場合、PSS メモリは 1GB 未満に制御する必要があり、3GB デバイスの場合は 1.5GB 未満に制御する必要があります。
ほとんどのプロジェクトでは、PSS メモリはReserved Total より約 200MB ~ 300MB 高いため、2GB デバイスのReserved Total は 700MB 未満に制御し、3GB デバイスは 1GB 未満に制御する必要があります。
特に、UWA は Mono ヒープ メモリに注意を払う必要があると考えています。なぜなら、多くのプロジェクトでは、常駐性の高さ自体の問題やリークのリスクに加えて、Mono ヒープ メモリのサイズも GC 時間に影響を与えるからです。 UWA は、80MB 未満に制御するのが最善であると考えています。
次の表は、UWA が提供する各リソース メモリの推奨基準を示したもので、より厳しいものです。ただし、開発者は自分のプロジェクトの実際の状況に応じて調整する必要があります。たとえば、2D プロジェクトではほとんどすべてのメッシュ リソースの使用が節約され、他のリソースの基準は大幅に緩和されます。
より詳細な規格については、UWA オンライン製品で直接表示できます。
プロジェクトの実際の状況に基づいてメモリ標準が策定された後、一般的にアートとプランナーとさらに交渉して、合理的なアート仕様パラメーターを与え、それをドキュメントに書き込む必要があります。
仕様が設定された後、プロジェクト内のすべてのアート リソースが仕様を満たしているかどうかを定期的に確認し、適時に修正および更新します。アートが準拠しているかどうかを確認するプロセスでは、Unity が提供するコールバック関数を使用して自動化ツールを記述し、効率を向上させることができます。 「Unity リソースを自動化的に規範する実践」(中国語注意)を参照できます。
リソースを高、中、低バージョンにバッチ処理できない場合、アーティストは画質レベルごとに異なるリソースを作成する必要があります。
1.3 ローカル リソース検出サービス – プロジェクト リソースの検出
各リソース メモリのエンジン設定項目は煩雑で、実行時にすべてを収集できるわけではありません. 以下に示す内容は、多くのプロジェクトで共通かつ重要な問題ですが、実際のプロジェクトの状況はより複雑です。ローカル リソース検出サービスのプロジェクト リソース検出インターフェイスを通じて、リソース設定項目に関するより多くの問題が見つかることがよくあります。関連するリソースのメモリ使用量に影響を与えるだけでなく、状況に応じて CPU 時間と GPU にさまざまな程度の負荷がかかります。
この目的のために、UWA は経験に基づいて検出ルールとしきい値を設計し、これに基づいてこれらの問題を含むリソースを収集およびカウントし、対応する最適化の提案を提供して、開発者がリソースのより詳細な調査と最適化を行えるようにしました。
2.よくある共通問題
このセクションに記載されている問題は特定のものではなく、1 つのリソース メモリにのみ発生するものではありません。したがって、重複を避けるために、ここでは統一的に説明します。
2.1 擬似冗長現象
UWA GOT オンライン リソース モードで報告されるリソース使用の具体的状況(以下、リソース一覧と呼びます) では、特定のリソースの最大数が 1 よりも大きいことがよくあります。最大数は、リソース使用量の非常に重要な指標でもあります。最大数というのは、同じフレーム内の同じリソースの最大数量を指します。理論的には、最大数というパラメーターは 1 を超えてはいけません。1 を超える場合、擬似冗長リソースと呼ばれます。
一般に、この問題は AssetBundle リソースのロードによって引き起こされます。つまり、AssetBundle ファイルを作成するときに、一部の共有リソース (テクスチャ、メッシュなど) が複数の異なる AssetBundle ファイルに同時にパッケージ化されますが、依存関係のパッケージ化は実行されません。そのため、これらの AssetBundle がロードされたときに、同じリソースの複数のコピーがメモリ内に現れ、つまりリソースの冗長を引き起こしました.。厳密な検出と改善を行うことをお勧めします.
擬似冗長性がある現象が見つかった場合は、UWA オンラインの AssetBundle 検出ツールを使用して、AssetBundle の冗長性に本当に問題があるかどうかを確認し、AssetBundle の冗長性を減らすことを試みることができます。冗長リソースのメモリサイズに応じて、冗長問題の最適化優先度を決定することをお勧めします。
「擬似冗長リソース」というのは、検出プロセス中に、プロジェクトの実行中に冗長リソースを検索してユーザーにフィードバックしようとすることを意味することに注意してください。ただし、この検出の 100% の正確性を保証することはできません。これは、リソースの名前やメモリ使用量などの属性に基づいて判断基準を設定しているためです (リソースの種類によっては、Read/Write、期間などの属性があり、リソース一覧に示された属性を基準にします)。 2 つのリソースの名前やメモリ使用量などの属性が一致している場合、2 つのリソースが同じリソースである可能性がある、つまり、そのうちの 1 つが「冗長な」リソースであると見なされます。ただし、リソースは異なりますが、属性は同じであるプロジェクトのケースが実際にあります。したがって、上記のルールによって抽出されたリソースを「擬似冗長リソース」として分類します。したがって、それが本当に冗長なリソースであるかどうかは、プロジェクトの状況とオンラインの AssetBundle 検出レポートを組み合わせて結論を出す必要があります。
2.2 名前のないリソース
リソース一覧に、リソース名が n/a のリソースがある場合があります。一般的に言えば、n/a という名前のリソースはコード内でnewされたが、名前は付けられていません。リソースの統計と管理を容易にするために、.name メソッドを使用してこれらのリソースに名前を付けることをお勧めします。特に、重大な冗長性または個々のメモリ使用量を持つ n/a リソースには注意を払い、厳密にチェックする必要があります。
2.3 常駐リソースメモリが大きい
リソース一覧では、リソースのライフ サイクル 曲線と組み合わせば、メモリ使用が大きい一部のリソースは、メモリにロードされた後、メモリに常駐し、テスト プロセス終了までにアンロードされないことがわかります。後半になればなるほどメモリ使用が大きくて最大値が大きくなります。この問題に対し、これらのリソースがメモリに常駐する必要があるかどうかを確認することをお勧めします。不要になった場合は、シーンが切り替わったときにアンインストールされない理由を確認する必要があります。単一のシーンに持続する長期的なリソースについては、手動アンインストールを検討できます。
リソースが常駐しているかどうかの検討には、メモリのプレッシャーと CPU 時間のプレッシャーとの間のトレードオフが伴います。簡単に言えば、現在のプロジェクトのメモリ プレッシャーが高く、シーン切り替え時の CPU 時間プレッシャーが小さい場合は、キャッシュ戦略の変更を検討し、シーンが切り替わる時、
次のシーンで使用されていないリソースをアンロードすることができます。必要な時に再度ロードできます。
3.テクスチャ リソース
3.1 テクスチャフォーマット
通常、不適切なテクスチャ フォーマット設定は、テクスチャ リソースが大量のメモリを占有する主な理由の 1 つです。アート リソースの標準が確立され、テクスチャ フォーマットが一律に変更された多くのプロジェクトでも、RGBA32、ARGB32、RGBA Half、RGB24 などのフォーマットのテクスチャ リソースが多数存在することは数え切れません。これらの形式のテクスチャは大量のメモリを消費するだけでなく、ゲーム パッケージのサイズが大きくなったり、これらのリソースの読み込みに時間がかかったり、テクスチャの帯域幅が高くなったりするなどの問題を引き起こします。
この種の問題の主な理由は次のとおりです。「ネットをすり抜ける魚」が存在します。たとえば、アートのネーミングが標準化されていないためにコールバック関数によって変更されなかったり、コードではテクスチャ形式が設定されていなかったりなどの原因が考えられます。または、ターゲットのテクスチャ形式はハードウェアまたはテクスチャリソース自体にサポートされていないため、テクスチャは非圧縮形式として解析されたからのこともあるかもしれません。
前者の場合、リソース一覧で問題のあるリソースを見つけた後、プロジェクトに戻って自分で確認および修正する必要がありますが、後者の場合、UWA が推奨するハードウェア対応のテクスチャ 形式には、主に ASTC と ETC2 が含まれます。
ETC2 形式では、対応するテクスチャの解像度が 4 の倍数である必要があります。対応するテクスチャが Mipmap で有効になっている場合、解像度は厳密に 2 のべき乗である必要があります。そうしないと、テクスチャは非圧縮形式に解析されます。
3.2 解像度
テクスチャ リソースの解像度 (つまり、リソース一覧内の長さと幅のパラメーター) も、過剰なメモリ使用の主な原因です。一般に、解像度が高いほど、メモリ使用量が大きくなります。これらの中で最も重要なのは、より大きな解像度 (通常は 1024 以上) を占めるテクスチャです。モバイル プラットフォームの場合、細かすぎるパフォーマンスはプレイヤーの肉眼では違いがわかりにくく、解像度が大きすぎると不要な無駄が生じることがよくあります。
異なるモデルで異なる解像度のテクスチャ リソースを使用することは、非常に実用的で操作が簡単なグレーディング戦略です。 これはアトラスにも適用します。特に、Unity は SpriteAltas 用の Variant 関数を提供します。これにより、元のアトラスをすばやくコピーし、スケール パラメーターに従ってバリアント アトラスの解像度を下げることができます。
3.3 Read/Write Enabled
前述のように、テクスチャの使用したメモリは GFX メモリ、つまり GPU に渡される部分で計算されます。 Read/Write Enabled オプションがオンになっているテクスチャも、CPU 側でもう一回保存されたので、リソースのメモリ使用量が 2 倍になります。
UWA GOT オンライン リソース モード レポートのリソース一覧またはローカル リソース検出レポートは、どのテクスチャでRead/Write Enabledオプションが有効になっているかを直接示します。実際、実行時に変更する必要のないリソースは、Read/Write Enabled オプションを有効にする必要はありません。開発者は不要な設定を確認して閉じ、メモリのコストを削減する必要があります。
3.4 ミップマップ
テクスチャに対して Mipmap が有効になっている場合、そのメモリ使用量は元のデータの 1.33 倍に増加します。シーン内の地形、オブジェクト、キャラクターなどの 3D オブジェクトの場合、テクスチャの Mipmap 機能を有効にすることをお勧めします。実行時の帯域幅を削減できますから。ただし、実機テスト レポートの Mipmap ページでは、ゲーム中に Mipmap テクスチャをオンにした各 Mipmap チャネルの画面比率の傾向がカウントされていることに注意してください。シーン内の 3D オブジェクトが大きな領域で Mipmap チャネルの 1/2 または 1/4、1/8 を使用している場合、3D オブジェクトが使用するテクスチャ解像度が高すぎて、無駄があることを意味します。それ。代わりに、解像度の低いテクスチャを使用できます。
ただし、2D プロジェクトまたは UI インターフェイス リソースの場合は、不要なメモリコストを避けるために、対応するテクスチャのミップマップ機能をオフにすることをお勧めします。
3.5 異方性およびトリリニア フィルタリング
テクスチャの異方性フィルタリングを有効にすると、地面などのオブジェクトの表示に役立ちますが、GPU レンダリング帯域幅が増加します。原則として、テクスチャを圧縮してサンプリングするとキャッシュ内の情報が読み取られますが、読み取られない場合はシステム メモリが GPU から遠く離れる場所で読み取られるため、クロック サイクルが増加します。異方性がオンになり、サンプリング ポイントの数が増えると、キャッシュミスの確率が増加し、帯域幅がさらに増加します。エンジンでは、スクリプトを使用してテクスチャ リソースの異方性をオフにすることができます。または、オンにする必要があるテクスチャについては、エンジンでサンプル数を 1 ~ 16 に設定できます。またできるだけ低い値を設定ください。
テクスチャをトライリニア フィルタリングに設定すると、異なるミップマップ チャネル間でテクスチャがぼやけ、バイリニア フィルタリングと比較して GPU レンダリング帯域幅が増加します。 Trilinear 補間は 8 サンプリング ポイント (bilinear は 4 サンプリング ポイント) を採用しますが、これも Cache Miss の確率を高め、帯域幅の増加につながります。Trilinear フィルタリングはできるだけ避ける必要があります。
これら 2 つのサンプリング方法のテクスチャも、開発者が確認できるように、UWA のローカル リソース検出によってカウントおよび一覧表示されます。
3.6 アトラスの作成
不十分な科学アトラスの作成も、プロジェクトでよく発生する問題です。最大数が高いアトラス テクスチャがリソース一覧に表示されることがありますが、必ずしも冗長しているわけではありません。あるケースでは、多数の小さな画像が同じアトラスにパッケージ化され、その結果、アトラスのテクスチャによって設定された最大解像度 (2048*2048 など) では多くの小さな画像を保持できず、れらの小さな画像をパックするためにリソースはより多くのテクスチャページが生成されます。したがって、ゲームがテクスチャページ内の小さな画像に依存している限り、リソースの下にあるすべてのページがメモリに読み込まれ、不要な無駄が発生します。したがって、一般的には 2 ~ 3 ページ以内に抑えることをお勧めします。
上記の極端な現象が発生しなくても、多くのプロジェクトでは「全身を動かす」という現象も発生します。つまり、アトラス内の 1 つまたはいくつかの小さな画像のみが使用されますが、大量のメモリを占有するテクスチャ全体がメモリに読み込まれます。
このため、パッケージ化されたアトラスを作成するときは、小さな画像の使用シーンと分類に厳密に従うことが非常に重要な戦略です。テクスチャが塗りつぶされずに無駄が生じないように適切な解像度を選択することも、開発者が注意を払う必要があるポイントです。
3.7 TextMeshPro を使用する場合
TextMeshPro は、UI コンポーネントにより優れたパフォーマンスと便利な機能を提供できるため、多くの開発者に好まれています。しかし、TMP を使用して生成された TMP フォント アトラス テクスチャ (名前に SDF Atlas が含まれるテクスチャ、Alpha 8 形式) にも、注目に値するいくつかの落とし穴があります。
(1) フォントリソース一覧と組み合わせると、TMP アトラス テクスチャに対応する .ttf フォント ファイルがメモリ内にあることがわかります。 TMP フォント アトラスがダイナミック フォントであることを示します。プロジェクトの開発が終了し、ゲームで使用される文字が動的フォントの Altas テクスチャに追加されたら、動的 TMP を静的 TMP にリセットし、.ttf ファイルへの依存を削除することを検討してください。この方法では、対応するフォント リソースはメモリに表示されません。ただし、フォントがユーザー入力にも使用される場合、この方法はお勧めしません。
(2) Atlas フォントのテクスチャの解像度が大きいです。この時点で、エンジン内で文字がアトラス テクスチャで埋められているかどうか、およびテクスチャの制作と生成が適切であるかどうかを確認することをお勧めします。動的 TMP の場合、テクスチャの 3/4 未満しか占めていないなど、いっぱいでない場合は、Multi Atlas Textures オプションをオンにして、テクスチャ サイズを設定することを検討できます。たとえば、40964096 の 1 つのテクスチャを3つの20482048 テクスチャに変更させば、32MB-3*8MB=8MB のスペースを節約できます。
(3) リソース一覧に TMP 関連のリソース (LiberationSans SDF Atlas, EmojiOne) があります. これらはすべて TMP のデフォルト設定です. Project Settings-TextMesh Pro Settingsでこれらのデフォルト リソースへの依存を削除したら、メモリに表示されなくなります。
Multi Atlas Textures は動的 TMP のオプションであるため、(1) と (2) を同時に使用することはできず、プロジェクトの実際の状況に応じて選択できます。
3.8 ローカルリソース検出を使用してテクスチャの問題を検出する
ローカルリソースの検出には、「圧縮されていない形式のテクスチャ」、「サイズが大きすぎるテクスチャ」、「Read/Writeオプションが有効になっているテクスチャ」、「Mipmap オプションが有効になっているSpriteテクスチャ」、「異方性フィルタリングが有効になっているテクスチャ」などのルールが含まれています。これらのルールは、開発者が潜在的なパフォーマンスの問題を持つテクスチャ リソースを正確に特定するのに便利です。
4.メッシュリソース
4.1 頂点数と面数
頂点と三角形の面数が多すぎるメッシュリソースは、メモリ使用量が高くなるだけでなく、クリッピングにも不利で、レンダリングの面数の増やされやすくなります。これらのメッシュに対しては、一方で、メッシュを単純化し、頂点と面数を減らしてローエンドおよびミッドエンドモデルのグレーディング用の低ポリゴンモデルを作成します。もう一つは、複雑な地形および建物など単なる頂点数が過多の静的メッシュの場合、若干の小さな重複したメッシュに分割して再結合することを検討できます。バッチ操作が適切に行われている限り、カリングの計算時間が少しかかりますが、同じ画面にレンダリングされる面数を減らすことができます。
4.2 頂点属性
統一されたアート リソース標準がなく、インポート時に処理されない場合、プロジェクト内のメッシュに多くの「余分な」頂点データが含まれている可能性があります。ここでの「余分な」データとは、レンダリング中にシェーダーで必要とされないデータがデータに含まれていることを意味します。たとえば、メッシュ データに、Position、UV、Normal、Color、Tangent などの頂点データが含まれているが、レンダリングに使用される Shader で必要なのは Position、UV、Normal だけである場合、 Color と Tangent は「余分な」データです。その中で、小さなメッシュ リソースには頂点属性があり、これによりCombined Meshにも頂点属性が付いたので、注意が必要です。
この問題の場合、比較的簡単な方法は、「Optimize Mesh Data」オプションを開こうとすることです。このオプションは、Player SettingのOther Settingsにあります。オンにすると、エンジンはパブリッシュ時にすべてのメッシュデータを走査し、「余分な」データを削除してデータ サイズを縮小します。ただし、開発チームは、ランタイムの場合にマテリアルの変更が必要なメッシュに特別な注意を払うことをお勧めします。実行時にあるGameObjectをより複雑なより多くの頂点属性にアクセスするマテリアルに変更する必要がある場合は、エンジンが使用されるメッシュを削除しないように、公開する前にこれらのマテリアルを対応するプレハブにマウントすることをお勧めします実行時。
4.3 Read/Write Enabled
リソース一覧では、頂点属性が-1(または「-」)で表示されないメッシュリソースが多数カウントされることがよくあります。頂点属性情報は、メッシュリソースに対してRead/Writeが有効になっている場合にのみ、UWA レポートによって収集できます。この時点で、頂点属性が -1 と表示されず、メッシュのメモリ使用量が増加します。一般的に言えば、CPU 側で変更する必要のないメッシュは、Read/Writeを有効にする必要はありません。これらのメッシュのRead/Write属性は、エディターのAPI を介して、または FBX のメッシュのインスペクター ウィンドウで直接変更できます。
4.4 ローカルリソース検出ツールを使用してメッシュの問題を検出する
ローカルリソース検出には、「面数が多すぎるメッシュ」、「Color属性を持つメッシュ」、「Tangent属性を持つメッシュ」、「Normal属性を持つメッシュ」、「UV3 または UV4 を持つメッシュ」「プロパティのグリッド」、「Read/Writeオプションが有効になっているメッシュ」などのテストルールは含まれます。これで開発者がパフォーマンスの問題の可能性があるメッシュリソースを正確に特定できます。
5.アニメーションリソース
一般的に、メモリ使用量が 200KB を超えて短いアニメーション リソースは、メモリ使用量が大きいアニメーション リソースと見なすことができ、最適化の余地があります。アニメーション リソースの最適化方法は次のとおりです。
(1) Animation TypeをGenericに変更します。他の Legacy タイプと比較すると、Generic は実際には Unity の Mecanim アニメーション システムの新しいバージョンを使用しており、全体的なパフォーマンスははるかに優れています。一般に、古いバージョンのアニメーション システムを使用することはお勧めしません。第三種のHumanoidは同様にキャラクター用の新版アニメーションシステムの特別なワークフローです。柔軟な再利用性という利点がありますが、モデルのボーン (つまり、ヒューマノイド ボーン) の数に要件があり、必要に応じて選択できます。
(2) Anim. Compression を Optimal に変更します。 Optimal を使用すると、Unity は複数のアルゴリズムから最適な曲線表現を自動的に選択できるため、占有するストレージ スペースが最小になります。Keyframe Reductionは比較的安定した保守的なアルゴリズムであり、アニメーションのパフォーマンスに影響を与える可能性は低くなります。
(3) Resample Curves オプションをオフにします。公式ドキュメントでは、このオプションを有効にすると一定のパフォーマンスが向上すると書かれていますが、実際には「Unity リソースの自動化仕様の実践」によると、上記の Resample Curves を有効にすることによるパフォーマンスの向上は、ロードではなく再生に反映され、影響は最小限であり、逆に、アニメーションのパフォーマンスが誤ったものになる可能性があります。したがって、実験データと組み合わせると、ほとんどの場合、このオプションはオフにすることをお勧めします。
(4) API を使用して、アニメーション リソースのスケール カーブと圧縮されたアニメーションの精度をカリングすることを検討します。その中で、アニメーションの精度を圧縮する実践は「Unity アニメーションファイル最適化」(中国語注意)を参照できます。
上記の 4 つの方法は、アニメーションリソースのメモリ使用量を効果的に削減できますが、(2) と (4) は、よく見られないかもしれないが、理論的にはアニメーションの精度が失われる原因となります。 開発チームが自らデバッグしてアニメーションのパフォーマンスに影響を与えないようにメモリ使用量を最適化することをお勧めします。
ローカル リソースの検出では、「Compression != Optimalアニメーション リソース」、「アニメーションのインポート設定で ResampleCurve がオフになっていない」、「Scale曲線を含むアニメーション クリップ」、「高精度のアニメーション クリップ」などが含まれます。前述のとおり、検出ルールは、パフォーマンスに問題がある可能性のあるアニメーション リソースを開発者が正確に特定するのに役立ちます。
6.オーディオリソース
再生時間の長い BGM と、再生時間は短いがメモリが大きい従来のオーディオ リソースには、最適化の余地があります。オーディオ リソースの最適化方法は次のとおりです。
(1) Force To Mono を開きます。オーディオ リソースの Force To Mono をオンにすると、チャネルが失われる代わりに、オーディオが自動的にモノラルにミックスされるため、パフォーマンスへの影響が少ないという前提でオーディオ メモリが大幅に削減されます。
(2) ロード タイプをCompressed In MemoryまたはStreamingに変更します。Compressed In Memory はほとんどの通常のオーディオに適していますが、Streaming は長くてメモリ使用が大きいBGMに適しています。
(3) Compressed In Memory のオーディオについては、その圧縮形式 (Compression Format) を Vorbis、MP3 などのより圧縮率の高い形式に変更します。
(4) Vorbis および MP3 圧縮形式のオーディオの場合、引き続き Quality パラメータを下げて、メモリをさらに圧縮することができます。
上記のいずれの方法でも効果的にオーディオ リソース メモリを削減できますが (Streamingは 200KB 程度まで安定して削減できます)、一定の時間がかかったり、音質が低下したりするため、状況に応じて適切に選択します。
ローカルリソースの検出では、前述の「2 チャンネルのオーディオ」、「Streamingでロードされない長いオーディオ」、「高品質の Vorbis および MP3 圧縮がオーディオに使用されている」などの検出ルールが含まれているので便利です。開発者がパフォーマンスの問題の可能性があるオーディオ リソースを正確に特定できるようにします。
7.マテリアル資源
マテリアル リソース自体が占有するメモリは少なく、その数が多すぎると後述する Resource.UnloadUnusedAssets API の時間消費に影響するため、通常はその数を最適化する方法に注意を払います。
多くの場合、主にInstanceタイプの冗長なMaterialリソースが多すぎることが原因で、マテリアル リソースが多すぎます。一般的に言えば、このような状況が発生するのは、meshrender.material のパラメーターがコードを通じてアクセスおよび変更されるためです。そのため、Unity エンジンはエフェクトを実現するために新しいマテリアルをインスタンス化するため、メモリに冗長性が生じます。この点については、MaterialPropertyBlock を使用して最適化することをお勧めします。具体的な関連操作と例については、次の記事「MaterialPropertyBlock を使用してマテリアル プロパティ操作を置き換える」を参照してください。ただし、この方法は URP では適用できず、SRP Batcher を中断します。さらに、インスタンス以外のマテリアル リソースの擬似冗長現象に注意を払い、最適化する必要があります。これは繰り返されません。
数以外は、多くの場合、マテリアル リソースにはテクスチャ サンプリングとシェーダーの使用に関連する問題が含まれ、余分なメモリと GPU パフォーマンスの浪費が発生します。より注目すべきものは、UWA ローカル リソース検出レポートの検出ルールとしてもカウントされています。
純色テクスチャ サンプリングを使用するマテリアルの場合、テクスチャ サンプリングをカラー パラメーターに置き換えることができるため、1 つのテクスチャ サンプリングのコストを節約できます; 空のテクスチャ サンプリングを使用するマテリアルの場合、Unity は提供された組み込みのテクスチャをサンプリングしますが、計算された色は定数でやはりもったいないですし、無用なテクスチャサンプルを含むマテリアルについては、Unityの仕組みにより、シェーダーが自動的にテクスチャサンプルを保存してくれるので、シェーダーを入れ替えても元々依存していたテクスチャは削除されません。ですから、誤った依存関係が発生する可能性があります。実際には不要なテクスチャがパッケージに取り込まれ、メモリの無駄になります.
8.Render Texture
8.1 レンダリング解像度
リソース一覧の一部の RT リソースは、プロジェクトの現在のレンダリング解像度を反映しています。 GPU とレンダリング モジュールへの負荷が高いプロジェクトの場合、ミッド・ローエンドのモデルでレンダリング解像度を下げることは、非常に直感的で効果的なグレーディング戦略です。一般的に、ローエンドモデルは、実機の解像度を使用しなくて、0.8 ~ 0.9 倍に減らすことを考慮します。多くのチームは 0.7 倍または 720P さえ選択します。
他の RT リソースの解像度が高すぎる場合、特に 2048*2048 を超えるリソースには注意が必要です。このような細かい RT を使用する必要があるかどうかを調査し、ローエンド実機での低解像度の影響を考慮する必要があります。
8.2 アンチエイリアシング
RT リソースの AA 倍数がリソース一覧に表示されます。複数の AA をオンにすると、RT のメモリ使用量が 2 倍になり、GPU に圧力がかかります。特にミッド・ローエンドの実機では、AA をオンにする必要があるかどうかを確認することをお勧めします。特にローエンドの場合、この効果をオフにすることを検討してください。
特に、一部の Huawei モデルでは 2 回の AA が失敗します。つまり、パフォーマンスの消費は発生しますが、アンチエイリアシング効果は実際には達成されていません。
8.3 後処理
一部の一般的な後処理関連の RT (ブルーム、ブラーなど) は、1/2 から解像度をレンダリングすることを開始します。1/4 からサンプリングし始め、同時にダウンサンプリングの数を減らすことを検討してください。これにより、メモリが節約され、後処理のレンダリングに対するプレッシャーが軽減されます。。
パフォーマンスの最適化の観点から、ローエンドおよびミッドレンジの実機では、あらゆる種類の後処理を完全にオフにすることをお勧めします。一般的な後処理効果のいくつかについては、以下の GPU セクションでさらに詳しく説明します。
8.4 URP の下での RT
URP を使用すると、さらに 2 つの RT リソース、_CameraColorTexture と _CameraDepthAttachment がレンダリング ターゲットとしてメモリに追加され、URP カメラの CopyDepth と CopyColor 設定がオンになっている場合、_CameraDepthTexture と _CameraOpaqueTexture が中間 RT として追加で生成されます。これら 2 つの RT がリソース一覧に表示されたら、CopyDepth と CopyColor が実際に使用されているかどうかを確認する必要があります。使用されていない場合は、不要な無駄を避けるためにオフにする必要があります。
9.シェーダー リソース
9.1 ShaderLab
Unity 2019.4.20 は、シェーダーのメモリ統計へのアプローチにおける転換点です。これまでは、シェーダーのメモリは主に ShaderLab でカウントされ、その後は主にシェーダー リソース自体でカウントされていました。
Unity 2019.4.20 より前のバージョンのプロジェクトの場合、ShaderLab メモリを表示するには、Unity プロファイラーで TakeSample が必要です。 メモリ使用量が高すぎるのはShader リソース自身であろうか、ShaderLab であろうか、Shader の数とバリアントの数を制御する必要があります。
9.2バリアントの数
シェーダー リソースが大量のメモリを占有し、パッケージ本体を占有しすぎる主な理由は、バリアントが多すぎることです。プロジェクトのイテレーションでは、廃止されたキーワードや実際には使用されていないキーワードが存在する可能性があり、その結果バリアントが増加しつつあります。または、Shader が複雑で、一部のキーワードの組み合わせが使用されなくなり、結果として多くのバリアントが冗長になることがあります。シェーダー検出機能は、UWA のローカル リソース検出で提供されており、バリアントの数を確認し、バリアントが多すぎるシェーダー リソースを見つけることができます。
上記の状況に対応して、Unity はプロジェクトが AssetBundleをパッケージ化する時またはBuild 時に未使用のキーワードまたはキーワードの組み合わせに関連するバリアントを排除するためのコールバック関数を提供します。シェーダー バリアントを削除する方法については、「Stripping scriptable shader variants」を参照してください。
9.3 冗長性
シェーダーの冗長性には特別な注意が必要です. シェーダーの冗長性はメモリの増加につながるだけでなく, 解析の繰り返しを引き起こす可能性があります。つまり、ロード時の不要なShader.ParseとShader.CreateGPUProgram APIのコール時間を引き起こします。
9.4 Standard Shader
リソース一覧で Standard、ParticleSystem/Standard Unlit が見つかりました。これら 2 つの Shader バリアントは数が多く、読み込み時間が非常に長く、メモリ使用量も大きすぎるため、プロジェクトで直接使用することはお勧めしません。その理由は、インポートされた FBX モデルまたは Unity によって生成された一部の 3D オブジェクトが独自のDefault Materialを使用し、Standard Shaderに依存していることが一般的です。調査して簡素化することをお勧めします。また、UWA オンラインの AssetBundle 検出ツールを使用して、どのAssetBundle のどのリソースが Standard Shader および ParticleSystem/Standard Unlit を参照しているのかを確認することもできます。確かにStandard Shader または ParticleSystem/Standard Unlit を使用する場合は、自分で必要なバリアントのみが含まれるshaderを書き直すことを検討してください。
9.5 ローカル リソース検出を使用してシェーダーの問題をトラブルシューティングする
ローカル リソースの検出には、「プロジェクト内: グローバル キーワードが多すぎるシェーダー」、「プロジェクト内: バリアントが多すぎるシェーダーが生成される可能性があります」、「ビルド後: バリアントが多すぎるシェーダーが生成される」、「Standard Shaderのマテリアルが使用されている」など上記の検出ルールは、開発者が潜在的なパフォーマンスの問題を抱えている Shader リソースを正確に特定できるようにするために使用されます。
10.フォント リソース
1 つのフォント リソースのメモリが 10MB を超える場合は、フォント リソースのメモリが大きすぎると考えられます。 FontPruner フォント削減ツールまたはその他のフォント削減ツールを使用して、フォントをスリム化し、メモリ使用量を削減することを検討してください。
また、プロジェクト内のフォントの数が多すぎる場合にも注意が必要です。各フォントはフォント テクスチャに対応するため、フォント リソースとテクスチャの数も増加し、より多くのメモリを占有します。
11.パーティクルシステム
リソース一覧をパーティクル システム曲線と組み合わせると、多くのプロジェクトのメモリ内のパーティクル数は、実際のPlayingパーティクル数よりもはるかに多くなります。
このとき、イテレーションの過程で廃止されたが削除されていないパーティクルリソースや、制作過程でテストされたが依存が解除されていないコンポーネントがあるかどうかを確認する必要がある一方で、 不必要なパーティクル キャッシュを減らすために、パーティクル キャッシング戦略を最適化することを検討できます。
12.モノヒープメモリ
UWA GOT オンライン モノ モード レポートは、開発者がプロジェクトのヒープ メモリの問題を分析するために、ヒープ メモリ具体の割り当てとヒープ メモリ リーク分析の 2 つの主な機能を提供します。
12.1 サステイン/ピーク割り当てスタック
ヒープメモリの特定割り当てページでは、高ヒープメモリ割り当て関数の特定のスタックを確認できます。主に 2 つの形式のヒープ メモリ割り当てに注目します。
1 つは、単一の高ヒープ割り当てです。この種のピークは、一般的にゲーム序盤の検針操作に起因する大きな割り当てで発生し、開発者は特定のスタック情報に基づいて妥当かどうかを確認する必要があります。ゲームの実行プロセス中にヒープ メモリ割り当てのピークがまだある場合は、注意を払う必要があります。
もう 1 つは、持続的な高いヒープメモリ割り当てです。プロジェクト内で毎フレームまたは数フレームごとにヒープメモリが多く割り当てられる現象が発生している場合は注意が必要です。継続的に高いヒープ メモリ割り当てを行うと、GC 頻度が増加し、ゲームが頻繁に停止することになります. スタックを使用して、どの子ノードが継続的にヒープ メモリを割り当てているかを確認できます。
12.2 リーク分析
リーク分析ページでプロジェクト内の各関数のヒープ メモリの常駐を確認します。グラフの前後の 2 つのサンプリング フレームを選択して比較すると、スタックからのヒープ メモリ常駐の変化を表示し、常駐の増加によって主にどのスタック割り当てが発生したかを確認できます。
一方では、ヒープメモリの継続的な増加によって引き起こされるリークのリスクを回避できますが、他方では、常駐の高い関数を最適化し、それらを時間内に解放することで、単一の GC にかかる時間を短縮できます。通常、GOT Online Mono モードを 1 時間など、できるだけ長くテストすることをお勧めします。そうしないと、多くの場合、リークの問題を明らかにすることが困難になります。
13.その他のメモリ
13.1 Lua
UWA GOT オンライン Lua モードは、Lua スクリプト言語のパフォーマンス テストを提供します。
そこに表示される関数名の形式は、関数名@ファイル名:行番号です。
レポートで提供されるLuaファイル名/行番号/関数名から、CPU時間のボトルネック機能とCPU時間のピークの具体的な原因を突き止めることができます。 Lua 関数の命名形式は X@Y:Z で、X は関数名です。取得できない場合、X はデフォルトのunknownになります。Y は関数が定義されているファイルの場所です。Z は関数が定義されている行です。Lua スクリプトがバイトコードとして実行される場合、この値は常に 0 になることに注意してください。そのため、テスト時にはできるだけ Lua ソース コードを使用して実行することをお勧めします。
Lua によって割り当てられたメモリについて、レポートの折れ線グラフは、30 フレーム内のデータの最大値をデータ ポイントとして選択します。折れ線グラフの傾向によると、開発者はプロジェクトの実行プロセス中にヒープ メモリの割り当てを一般的に理解するのに役立ちます。その中で、ヒープメモリの減少はGCが発生したことを意味します。特定のメモリ割り当てとリーク分析および機能の表示は、Mono モード レポートに似ています。
Lua レポートのもう 1 つの重要な機能は、Mono オブジェクト参照統計です。
原理レベルから、Unityオブジェクトと Luaオブジェクトをリンクするために、オブジェクト プールが Unity Mono 仮想マシンで維持されます。シーン内の Unity オブジェクトがDestroyedされると、シーンは消えますが、Lua レイヤーが Usedata 参照を保持しているため、オブジェクト プールは Unity オブジェクトを解放できません。オブジェクトがテクスチャ、メッシュ、およびその他の関連リソースを参照している場合、メモリリークが発生がちです。このとき、Lua 層の関連オブジェクトを空 (nil) にする必要があります。デリファレンス後、Unity オブジェクトは次の GC が発生した後に再利用できます。この機能の意義は、開発者がこのようなリークリスクのトラブルシューティングを支援することです。
レポートには、Mono オブジェクト参照ヒストグラムが表示され、黒い部分が Destroy されていないオブジェクトの数を表します。Lua 側の GC の影響により、一部の Destroyed オブジェクトが存在します。現時点では、安定しているかどうかに注意する必要があり、上昇し続ける場合は注意が必要です。
対応するフレームを選択すると、そのフレームの Mono オブジェクト タイプのリストがリストに表示されます。その中に:
オブジェクト タイプ: Unity オブジェクトの具体のタイプを表します。
オブジェクトの数: このタイプのオブジェクトの数を示します。
Destroyedオブジェクトの数: Destroyedされたが、Lua レイヤーにはまだ関連する参照があるオブジェクトの数を示します。 Destroyed オブジェクトの数に注意する必要があります。数が多い場合、C# ヒープ メモリがリークする危険性があります.
13.2 プラグインとサードパーティ ライブラリ
プラグインや Wwise などのサードパーティ ライブラリの使用は非常に一般的ですが、実行時に定量的かつ直感的に統計をカウントすることは通常不可能です。ただし、一般に、それらは多くのメモリを占有しません。上記のメモリ最適化ポイントがチェックされた後でのみ、PSS メモリと Reserved Total の値の間に大きなギャップがあることが判明し、その後、プラグインまたはサードパーティのライブラリまたはその開発者が提供する方法は、的を絞った方法で最適化でき、パフォーマンスの優れた代替手段を検討することさえできます。
UWA公式サイト:https://jp.uwa4d.com
UWA公式ブログ:https://blog.jp.uwa4d.com
UWA公式Q&Aコミュニティ(中国語注意):https://answer.uwa4d.com
これも興味あるかも
-
原理から応用まで ゲームでの動的解像度
January 4, 2023 -
Unityゲームの使用メモリを最適化しよう
December 21, 2022 -
ASTC テクスチャ圧縮形式の紹介
December 14, 2022