Unity を検索

Unity 2021 LTS におけるプロファイリング:何を、いつ、どのように行うか

2022年6月1日 カテゴリ: テクノロジー | 23 分 で読めます
A red mannequin in a 3d setting
A red mannequin in a 3d setting
取り上げているトピック
シェア

Unity のプロファイリングツール群に習熟することは、皆さんのゲーム開発に使う道具に最も有用なスキルの 1 つを加えることを意味します。徹底的にプロファイリングを行うことで、ゲームのパフォーマンスを大幅に向上させることができます。そこで、新しくリリースされた e ブック「Ultimate guide to profiling Unity games」から、重要なヒントをご紹介します。

没入感のあるゲーム体験を実現するには、スムーズなパフォーマンスが不可欠であることは、ゲームクリエイターなら誰でも知っていることです。そのためには、ゲームのプロファイリングを行う必要があります。どのツールをどのように使うかだけでなく、いつ使うかも知っておく必要があります。

社内外の専門家の協力を得て、70 ページ以上に及ぶ一歩進んだプロファイリングのガイドを作成しました。Unity でアプリケーションのプロファイリングを行い、パフォーマンスのボトルネックを特定する方法など、ベストプラクティスに関するアドバイスや知識がまとめられています。 

e ブックの中から参考になるヒントをいくつか取り上げてみましょう。

プロファイリングを行うタイミング

プロファイリングはいわば探偵の仕事です。アプリケーションのパフォーマンスが低下している理由や、コードが過剰なメモリを割り当てている理由など、謎を解明していくのです。

究極的には、プロファイリングツールは Unity プロジェクトの内部で何が起こっているかを理解するのに役立つものです。しかし、性能に重大な問題が明るみに出てから、探偵の道具について詳しく調べ始めるのでは遅いのです。

プロファイリングが最も効果を挙げるのは、ゲームを出荷する直前ではなく、プロジェクトの開発ライフサイクルの初期に計画を立てる場合です。それは、継続的、積極的、かつ反復的なプロセスです。早期に頻繁にプロファイリングを行うことで、皆さんや皆さんのチームは、プロジェクトの「パフォーマンスのサイン」を理解し、定着させることができます。たとえば、パフォーマンスが低下した場合、その低下が起きるタイミングを突き止め、迅速に改善することができます。

また、次に示すシンプルな 3 つの手順に従うことで、小さな単位で前後のパフォーマンス比較を行うことができます ― まず、大きな変更を加える前に、プロファイリングによってベースラインを確立します。次に、開発中にプロファイリングを行い、パフォーマンスや予算の使われ方を追跡します。最後に、変更を実施した後にプロファイリングを行い、期待した効果が得られたかどうかを検証します。

プロファイリングは Unity エディター内で行うのではなく、ゲームの開発用ビルドを使って行うことを推奨します。その理由は 2 つあります。

  1. スタンドアロンの開発ビルドから得られるパフォーマンスとメモリ使用量に関するデータは、エディター内でゲームをプロファイリングした結果と比較して、はるかに正確です。これは、プロファイラーウィンドウがエディター自体のデータを記録しているため、結果が歪んでしまうことが原因です。
  2. パフォーマンスの問題の中には、ゲームのターゲットであるハードウェアやオペレーティングシステムで実行されたときにのみ現れ、エディターだけでプロファイリングしていると見逃してしまうものがあります。

自由自在に使えるツール

最も正確なプロファイリング結果は、ターゲットデバイス上でビルドを実行してプロファイリングし、プラットフォーム専用のツールを使用してターゲットプラットフォームごとのハードウェア特性について詳しく調べることで得られます。

Unity には、エディター内とハードウェアの両方でコードを解析し最適化するための無料の強力なプロファイリングツールが付属していますが、Arm、Apple、Sony、Microsoft など、各プラットフォーム向けに設計された優れたネイティブプロファイリングツールも複数存在します。これらを組み合わせることで、すべてのターゲットデバイスのアプリケーションパフォーマンスの全体像をよりよく把握することができます。

利用できるツールの概要については、プロファイリングツールのページをご覧ください。

Unity のプロファイリングツールは、エディターとパッケージマネージャーで利用可能です。各ツールはプロセス(全体的な「すべての部分の総和」ワークフロー)のさまざまな部分のプロファイリングに特化しています。以下で紹介するプロファイラーを使いこなし、毎日の開発に使う道具の一部にしてしまいましょう。

  • Unity プロファイラーは皆さんが最初に使い、ここでほとんどの時間を使うであろうツールです。Unity エディター内で再生モードになっているアプリケーションのパフォーマンスを測定することも、開発モードでアプリケーションを実行しているデバイスに接続して使うこともできます。Unity プロファイラーは、オーディオや物理演算、レンダリングやアニメーションなど、さまざまなタスクにどれだけの CPU 時間が使われているかなど、アプリケーションのパフォーマンスに関するデータを収集し、表示します。まずはプロファイリングに関するこちらのコースをチェックしてみましょう。
  • Memory Profiler は、メモリパフォーマンスを詳細に分析し、プロジェクトやエディターの一部でメモリ使用量を削減できる箇所を特定することができます。Memory Profiler は現在プレビュー版ですが、Unity 2022 LTS で検証済みとなる予定です。
  • Profile Analyzer は、Unity プロファイラーの一連のフレームから、フレームやマーカーデータを集計して視覚化します。これは多数のフレームにわたる動作について調べる時に役立つもので、Unity プロファイラーですでに利用可能な単一フレーム分析を補完するものです。また、2 つのプロファイリングデータセットを比較し、変更内容がアプリケーションのパフォーマンスにどのような影響を与えるかを判断することができます。
  • フレームデバッガーは、実行中のゲームの実行を特定のフレームで停止させ、そのフレームをレンダリングするために使用された個別のドローコールを表示することができます。デバッガーでは、ドローコールをリストアップするだけでなく、1 つずつ順に実行していくことで、グラフィックスの要素からシーンがどのように構築されるかを確認することができます。
  • Profiling Core パッケージ は、Unity プロファイラーのキャプチャにコンテキスト情報を追加するための API を提供します。

ツールの使用方法

Unity のシニアエンジニアであり、上級者向けのプロファイリングに関する e ブックの共著者である Steve McGreal が、以下の概略的な資料をまとめました。リファレンスシートとして、ご自由にお使いください。

ツールの詳しい使い方は e ブックをご覧いただくとして、このフローチャートは、ワークフローを考える上で考慮すべき 3 つの主な観察事項を示しています。

Flowchart for how to use the Profiler for pinpointing where to focus optimization efforts

こちらのチャートの印刷用 PDF のダウンロードはこちらから行っていただけます。もっと詳しく知りたい方は、この記事の最後にまとめられた、各種プロファイリングツールの使用方法に関するリンク先のリソースを参照してください。

フレーム予算に収まっているか

ゲームを遊ぶ人がパフォーマンスを測る一般的な方法は、フレームレート(1 秒あたりのフレーム数)です。しかし、開発者である皆さんには、フレームレートではなくフレーム時間(ミリ秒単位)を使うことをお勧めします。

たとえば、実行時に 59 フレームを 0.75 秒でレンダリングし、次のフレームのレンダリングに 0.25 秒かかるようなゲームがあるとします。平均すれば 60 fps のフレームレートとなり聞こえは良いですが、実際には最後のフレームのレンダリングに 1/4 秒かかるため、プレイヤーは一瞬止まるように感じます。

ゲームのプロファイリングや最適化を行う際には、毎フレーム、定められた時間予算を守るように努めましょう。これは、スムーズで一貫したプレイヤー体験を実現するために非常に重要です。各フレームには、目標とする fps に応じた時間予算が設定されています。30 fps をターゲットとするアプリケーションでは、その予算が常に 1 フレームあたり 33.33 ms(1000ms / 30 fps)未満である必要があります。同様に、60 fps を目標とすると、1 フレームあたり使える時間は約 16.66 ms となります。

最近のコンソールゲームや PC ゲームの多くは、60 fps 以上のフレームレートを目標にしています。VR ゲームでは、プレイヤーに吐き気や不快感を生じさせることを避けるため、常に高いフレームレートを保つことがより重要になります。また、モバイルゲームでは、デバイスの過熱を避けるために、フレーム予算を制限しなければならない場合があります。たとえば、モバイルゲームでは、フレーム間で CPU と GPU を冷却できるように、フレーム予算を 21 ~ 22 ミリ秒に抑えつつ、30 fps を目指すというケースがあります。

Unity プロファイラーを使って、フレーム予算内で処理を行えているかを確認します。下の画像は、プロファイリングと最適化を継続的に行っている Unity で作ったモバイルゲームのプロファイリングのキャプチャです。ハイスペックなスマートフォンでは 60 fps、このキャプチャーのようなミドルレンジ・ローエンドのスマートフォンでは 30 fps を目標にしています。

Profiler framerate snapshot

これは、30 fps に必要なフレーム予算の約 22 ms の範囲内で、過熱することなく快適に動作しているゲームです。WaitForTargetfps は、VSync までのメインスレッドの時間と、レンダースレッドとワーカースレッドの灰色で表示されているアイドル時間のパディングを行っています。また、VBlank の間隔は、フレーム間で Gfx.Present の終了時間を見ることで観測することができます。タイムライン領域または上部のタイムルーラーにタイムスケールが表示を表示し、あるフレームの Gfx.Present の終了時間から次のフレームの終了時間までの間隔を計測することができます。

バッテリーの消費やサーマルスロットリングを考慮した予算の調整も含めフレーム予算の範囲内であれば、そこでのパフォーマンスプロファイリングを首尾よく完了できたことになります。今度はメモリ使用量を見て、同様に予算内かどうかを確認します。

フレーム予算内に収めてゲームを走らせられない場合の次のステップは、ボトルネックを検出することです。言い換えると、CPU と GPU のどちらがより時間を使っているかを調べるのです。CPU が原因なら、どのスレッドに最も負荷がかかっているかを調べましょう。そこにボトルネックがあります。

プロファイリングのポイントは、最適化のターゲットとなるボトルネックを特定することです。当て推量に頼るとボトルネックになっていない部分まで最適化してしまい、ほとんどあるいはまったく改善されないということも起こりえます。「最適化」の中には、ゲーム全体のパフォーマンスを悪化させるものもあるのです。

CPU メインスレッドバウンドになっていないか

メインスレッドは、デフォルトだとすべてのゲームロジックとスクリプトが動作する場所となっており、物理演算、アニメーション、UI、レンダリングなどの機能やシステムが実行される場所です。

メインスレッドバウンドになったプロジェクトがどのように見えるかの例として、以下のスクリーンショットをご覧ください。

Capture from a project that is main thread-bound
メインスレッドバウンドになったプロジェクトからのキャプチャ

レンダースレッドとワーカスレッドがフレーム予算内に収まっている直前の例に似ていますが、この例でのメインスレッドは多くの仕事を抱えて、フレーム全体を通して明らかに負荷が高くなっています。フレーム終了時のわずかなプロファイラーによるオーバーヘッドを考慮しても、メインスレッドは 45 ms 以上ビジー状態であり、このプロジェクトのフレームレートは 22 fps 未満となります。メインスレッドがアイドル状態になって VSync を待っているような兆候はなく、フレーム全体がビジー状態になっています。

次の段階として、フレームの中で最も時間がかかっている部分を特定し、その根本的な原因を突き止めます。Unity プロファイラーと Profile Analyzer の両方を使って、最大のコストを評価し、それに対処することができます。ボトルネックは、物理演算、最適化されていないスクリプト、ガベージコレクター(GC)、アニメーション、カメラ、UI が絡むところで発生することが多いです。問題の原因がすぐにわからない場合は、Deep Profiling および Call Stacks を有効にするか、ネイティブの CPU プロファイラーを使用してみてください。

95 ページに及ぶパフォーマンス最適化ガイドでは、皆さんがよく出会う落とし穴を列挙し、それらに備えるための対策を紹介しています。

CPU レンダースレッドバウンドになっていないか

レンダリング処理では、メインスレッドがシーンを調べ、カメラカリング、深度ソート、ドローコールバッチングを実行し、レンダリングするもののリストを作成します。このリストはレンダースレッドに渡され、レンダースレッドはこれを Unity 内部のプラットフォーム非依存の表現から、特定のプラットフォームの GPU に指示するために必要なグラフィックス API の呼び出しに変換します。

下に示したプロファイラーのキャプチャでは、メインスレッドが現在のフレームでレンダリングを開始する前にレンダースレッドを待機していることが Gfx.WaitForPresentOnGfxThread のマーカーで示されています。

A render thread-bound scenario on Profiler
レンダースレッドバウンドのシナリオ

レンダースレッドは、前のフレームからのドローコールコマンドをまだ送信していますが、メインスレッドからの新しいドローコールを受け入れる準備ができていません。レンダースレッドは、Camera.Render で時間を消費します。

Rendering プロファイラーモジュールは、フレームごとのドローコールバッチと SetPass コールの数の概要を共有します。 レンダースレッドが GPU に対して発行するドローコールがどれかを調査するのに最適なツールは、Frame Debugger です。レンダースレッドのボトルネックの一般的な原因は、ドローコールのバッチングの不備、シーン内に複数のアクティブなカメラがあること、非効率的なカメラカリングなどです。

CPU のワーカースレッドバウンドになっていないか

メインスレッドやレンダースレッド以外の CPU スレッドバウンドになってしまうことはそれほど一般的な問題ではありませんが、Data-Oriented Technology Stack(DOTS)を使用するプロジェクトでは、特に C# Job System を使用してメインスレッドからワーカースレッドに作業を移動させた場合、発生し得る問題です。

下の画像は、CPU 上で粒子流体シミュレーションを実行する DOTS プロジェクトの再生モードのエディター内表示のキャプチャです。

A DOTS-based project, heavy on simulation, bound by worker threads
シミュレーションが重く、ワーカースレッドバウンドになっている DOTS ベースプロジェクト

ご覧の通り、ワーカースレッドにジョブがぎっしりと詰まっています。これは、メインスレッドから大量の作業が移動していることを示唆しています。フレーム時間 48.14 ms とメインスレッドに見られる灰色の WaitForJobGroupID マーカーの 35.57 ms は、ワーカースレッドが、この CPU で 1 フレーム内に現実的に完了できる以上の作業を実行していることを示すことに注意してください。

WaitForJobGroupID は、メインスレッドがワーカースレッドで非同期に実行するジョブをスケジュールしていることを示しています。しかし、ワーカースレッドがジョブの実行を終了する前にこれらのジョブの結果が必要なのです。WaitForJobGroupID の下にある青いプロファイラのマーカーは、メインスレッドが待ち時間にジョブを実行し、ジョブの終了を早めようとしていることを示しています。

皆さんのプロジェクトのジョブは、この例のように並列化されていないかもしれません。おそらく、1 つのワーカースレッドで 1 つの長いジョブが実行されているだけでしょう。これは、ジョブがスケジュールされてから、そのジョブが完了しなければならないタイミングまでの時間が、ジョブの実行に十分な長さだけあれば、問題ありません。そうでない場合は、上のスクリーンショットのように、ジョブが完了するのを待つためにメインスレッドが停止する様子を目にすることになるでしょう。

CPU Usage プロファイラーモジュールのタイムライン表示で、Flow Events 機能を使用すると、ジョブがいつスケジュールされるか、いつその結果がメインスレッドで必要とされるかを確認することができます。効率的な DOTS コードの書き方については、DOTS のベストプラクティスをご覧ください。

GPU バウンドになっていないか

メインスレッドがレンダースレッドを待つ時間があると気づくことがあるかもしれません(Gfx.WaitForPresentOnGfxThread などの Profiler マーカーで表示されます)。しかし同時に、レンダースレッドに Gfx.PresentFrame や <グラフィックス API 名>.WaitForLastPresent のようなマーカーが表示される場合があります。これは、アプリケーションが GPU バウンドであることを意味します。したがって、全体のパフォーマンスを向上させるために、GPU のボトルネックに最適化の努力を集中させる必要があります。

下のキャプチャは、Samsung Galaxy S7 で Vulkan グラフィックス API を使っているときの様子を撮影されたものです。この例の Gfx.PresentFrame で費やされた時間の一部は VSync の待ち時間に関連している可能性もありますが、この極端に長いプロファイラーマーカーは、大部分の時間が GPU が前のフレーム をレンダリングし終えるのを待つために費やされていることの証です。

A capture from a GPU-bound mobile game
GPU バウンドになっているモバイルゲームのプロファイリングのキャプチャ

アプリケーションが GPU バウンドしている場合には、フレームデバッガーを使い、GPU に送信されるドローコールのバッチについて素早く把握しましょう。ただし、このツールは具体的な GPU のタイミング情報を提示することはできません。シーンがどのように構成されているかが明らかになるだけです。

GPU ボトルネックの原因を慎重に調査するために、適切な GPU プロファイラーを使って GPU キャプチャを調べます。使用するツールは、ターゲットハードウェアと選択したグラフィックス API に依存します。

GPU の性能低下の一般的な原因は、非効率的なシェーダー、高価なポストプロセッシングエフェクト、透明のオーバードロー(パーティクルエフェクトや UI が原因となることが多い)、サイズが大きいまたは圧縮されていないテクスチャ、過度にポリゴン数の多いメッシュ、高すぎる出力解像度(4K でレンダリングする)などがあります。

無料の e ブックを入手

A promotion of a profiling e-book

パフォーマンスの最適化とプロファイリングは、非常に大きなトピックです。より詳細な情報をお求めの方は、最近リリースした e ブック「Ultimate guide to profiling Unity games」をご覧ください。Integrated Support サービスチームのメンバーも含め、何人ものエキスパートが協力して作成した、80 ページを超えるヒント集となっています。

実はこの e ブックの作成に携わったメンバーの一部は、モバイルPC・コンソール向けのパフォーマンス最適化に関する、合わせて 100 ページを超えるガイドの作成にも協力しています。これらのガイドには、初手からボトルネックを作らないようにするための実践的なヒントが満載です。他にも情報に当たりたい方は、物理演算、UI、オーディオ設定モバイルコンソールでのグラフィックスとアセット、およびメモリとコードアーキテクチャについての過去のブログ記事シリーズをご覧ください。

エンジニア直通の連絡ルート、エキスパートのアドバイス、プロジェクトのガイダンスなどが得られる、Unity の Success Plan にご興味のある方は、こちらをご覧ください。

今後予定されているプロファイリング関連のウェビナー

3D model with robot figure on the right

今回新たにお送りする、SYBO Games、Arm、Unity のエキスパートによる Ultimate Profiling Tips ウェビナーでは、Unity とネイティブプロファイリングツールの両方を使用して、モバイルゲームに共通するパフォーマンスの課題を特定する方法についてのヒントが紹介されています。 

このウェビナーでは、以下の話題を取り上げます。

  • ローエンドからハイエンドまで、幅広いデバイスでスムーズなパフォーマンスを実現するために、無駄のない、パフォーマンスの高いコードを作成し、メモリ使用量を最適化するための考慮すべき重要なポイント
  • モバイルデバイスの貴重なバッテリーサイクルを節約するための熱制御の管理
  • ゲーム開発のすべての段階におけるプロファイリング戦略と、強固な方法論を構築するためのテストのやり方
  • Android のプロファイリングに関するエキスパートの知見

日本時間 2022 年 6 月 15 日深夜 0 時(2022 年 6 月 14 日 24 時)から開催されるラウンドテーブルとライブ Q & A セッション(英語)にぜひご参加ください。

探している情報が見つからない?

私たちは、皆さんの Unity アプリケーションの力を最大限に引き出すお手伝いをしたいと考えています。もし、私たちにもっと掘り下げてほしい最適化のトピックがありましたら、フォーラムでお知らせください。また、皆さんが好むフォーマットについてもお聞かせ願えれば幸いです。ご意見は、e ブックやその他の教材の改善に役立てさせていただきます。

2022年6月1日 カテゴリ: テクノロジー | 23 分 で読めます
取り上げているトピック
フォーラムでディスカッションに参加する