6 月に、Arm、Unity Accelerate Solutions チーム、および『Subway Surfers』の制作にあたった SYBO Games の専門家を招いてウェビナーを開催しました。そこで開催されたラウンドテーブルでは、モバイルゲームのプロファイリングのヒントと戦略、パフォーマンスの低下によるビジネスへの影響、SYBO Games が累計 30 億ダウンロードを記録したヒット作を生み出した方法などに焦点が当てられました。
ここでは、ウェビナーで取り上げきれなかったフォローアップの質問を紹介します。また、ウェビナー全編の録画をご覧になることもできます。
Profile Analyzer をコアエディターに統合する計画は当面ありませんが、この予定もプロファイリングツールの進化に伴って変更される可能性があります。
いいアイデアだと思いますが、このブログの時点では、イエスともノーとも言えません。将来的に検討するために、当社の研究開発チームと共有している要望です。
スタックトレースのない ANR のトラッキングについては、現時点では具体的な計画はありませんが、将来のロードマップに載せる項目として検討しようと思います。
プロダクトボードとフォーラムで、今後の機能を把握し、フィードバックを共有することができます。また、プロファイリングツールを使用した皆さんの体験談を知るために、アンケートを実施しています。プロファイリングツールを使ったことがある方(毎日でも一度でも)、最適化が必要なプロジェクトに携わっている方、ぜひご意見をお聞かせください。アンケートは 5 ~ 10 分程度で完了するように設計されています。
また、参加された方は、フォローアップインタビューに参加し、新機能のプロトタイプに望むものなど、開発チームに直接フィードバックをする機会も得られます。
多くの Unity ゲーム開発者がその経験から、ゲームのリリース時に 5 年前のデバイスとなるものをターゲットにすることで、最も多くのユーザーを確保することができると言っています。しかし、より高いグラフィック品質を目指すために、リリース時期の 3 年前のデバイスまでをターゲットにするチームも見受けられます。例えば、複雑なビジュアルを持つ 3D アプリケーションは、単純な 2D アプリケーションよりもデバイス要件は高くなります。この方法では、「最低スペック」を上げることができますが、初期のインストールベースの規模は小さくなります。これは基本的にビジネス上の決断です。古いデバイス用に開発しサポートするコストが、そのデバイスでゲームが動作した場合の収益を上回るかどうかです。
ゲームの技術的な要件によって、最小限のターゲットスペックが決まることもあります。そのため、最適化してもテクスチャメモリを大量に消費し、画質や解像度をどうしても下げられない場合、メモリが足りないスマートフォンを対象外としなければならなくなります。レンダリングソリューションがコンピュートシェーダーを必要とする場合、OpenGL ES 3.1、Metal、または Vulkanをサポートできないドライバーを搭載したデバイスは除外される可能性が高いです。
優先するターゲットオーディエンスの市場データを見ておくとよいでしょう。例えば、モバイルデバイスのスペックは国や地域によって大きく異なることがあります。ローエンドデバイスをテストに選ぶ前に、何が許容範囲なのかのベンチマーク目標を設定するため、いくつかのターゲット「予算」を定義することを忘れないでください。
何年にもわたって運営されるライブサービスのゲームでは、その互換性を継続的に監視し、実際のユーザーベースと市場の現行デバイスの両方に基づいて、時間の経過とともに適応させていく必要があります。
すべてのデバイスでワークロードが均一であれば、そうかもしれません。ただし、ハードウェアのベンダーやドライバーのバージョンが異なる場合は、その差異を考慮する必要があります。
グラフィックがリッチなゲームでは、グラフィックの忠実度に段階を設けるのが一般的で、忠実度のレベルが高いほど、相応のデバイスでより多くのリソースを必要とします。この段階の選択は自動的に行われることもありますが、ユーザー自身がグラフィカルな設定メニューから選択できるようになっているケースも増えてきています。このような開発スタイルでは、ゲームがサポートする機能やワークロードの階層ごとに、少なくとも 1 つの「最小スペック」のターゲットデバイスをテストする必要があります。
ゲームが実行されているデバイスの能力を認識して、必要に応じてグラフィックス出力を適応させる場合、ハイエンドのデバイスでは発揮されるパフォーマンスが異なってくる可能性があります。そのため、そのゲームでプログラムされている複数の品質レベルにそれぞれ対応したデバイスで必ずテストしてください。
注:このセクションでは、エキスパートからの回答が Arm からのものか、Unity からのものかを明記しました。
Arm:通常、開発者は CPU と GPU のモデル、および GPU シェーダーコア数に基づいて、粗い性能ビニングを行っているところをよく目にします。これは決して完璧ではありませんが、「だいたい正しい」という感じです。多くのスタジオは、デプロイされたデバイスからライブのアナリティクスを収集しているので、デバイス固有のオプトインまたはオプトアウトで自動化されたビニングを補完し、性能ビニングの正確さが十分でないところの問題に対処することが可能です。
前の質問と関連しますが、モバイルでは、グラフィックがリッチなコンテンツについて、ユーザーがエフェクトのオン・オフを選択できる設定メニューを用意し、ユーザーの好みに応じたパフォーマンスを選択できるようにする傾向が見られます。
Unity:デバイスのメモリや画面の解像度も、画質設定を選ぶ際の重要な要素です。テクスチャについては、エフェクトやポストプロセッシングで使用されるレンダーテクスチャが、高解像度スクリーンを備えるものの、それに見合うだけのメモリがないデバイスで問題を起こすことがあるので、開発者は注意する必要があります。
Arm:チームが最適化の対象とする階層の数は、実際にはゲームデザインとビジネス上の決定であり、ビジュアルの品質を押し上げることがゲームの価値提案にどれだけ重要であるかに基づいて決定されるべきです。ジャンルによっては全く関係ないかもしれませんが、ユーザーにとってはビジュアルの忠実度に高い期待を抱くでしょう。
Arm:ざっくり言って、テクスチャメモリの総量はベンダーやハードウェアの世代を問わず同程度であることが予想されます。ただし、メモリレイアウトやアライメントの制約による細かな違いがありますから、まったく同じにはなりません。
Arm:完全にコンテンツに依存します。CPU、GPU、DRAM の 3 つは、たとえ他の 2 つを完全に無視したとしても、激しく使い込まれればどれか 1 つだけでもハイエンドデバイスをオーバーヒートさせることがあります。正確なバランスは、実行するワークロードによって異なります。
Arm:Android では、デバイスがエネルギー消費を最適化するために周波数を常に調整するため、フレーム時間の最適化は誤解を招くものとなる可能性があり、フレーム時間そのものは不完全な指標となります。フレームあたりの CPU と GPU サイクル、およびフレームあたりの GPU メモリ帯域幅を監視し、周波数に依存しない何らかの値を得ることが好ましいです。必要なサイクル目標は、各デバイスのチップ設計によって異なるので、実験が必要です。
フレームレートを直接的に向上させなくても、消費電力を管理するという点ではどんな最適化も役に立ちます。例えば、CPU サイクルを削減すれば、CPU がゲームのクリティカルパスでなくても、熱負荷を軽減することができます。
それ以上に、メモリ帯域を最適化することは最も大きな省力化の 1 つです。DRAM へのアクセスは、チップ上のローカルデータへのアクセスに比べて桁違いにコストがかかるため、三角形数の予算に注意して、メモリ内のデータ型はできるだけ小さいものを使うようにしてください。
Unity:CPU クロック周波数がパフォーマンス指標に与える影響を抑えるために、一定の温度で動作するようにすることをお勧めします。これを行うには、いくつかのアプローチがあります。
一部のハードウェアでは、クロック周波数を固定することで、より安定したパフォーマンス指標を得ることができます。しかし、これはユーザーが使用するデバイスの多くを代表しておらず、実行時の性能を正確に報告するものではありません。基本的に、継続的インテグレーションのセットアップを使用している場合、時間の経過に伴うコードベースのパフォーマンスの変化をチェックするのに便利なテクニックです。
Arm:最近のドライバーとエンジンのビルドでは、利用可能な Vulkan 実装の品質が大幅に向上しています。したがって、同等のワークロードでは、OpenGL ES と Vulkan の間に性能差はないはずです(ある場合はご教授ください)。開発者が Vulkan へ切り替える速さが上がってきており、今後 1 ~ 2 年の間にデフォルトで Vulkan を選択する人が増えると思われます。もし Vulkan がパフォーマンスをうまく発揮できないという分野をご存知でしたら、私たちまでご連絡ください。ご意見はいつでもお待ちしております。
Arm:Arm Mobile Studio の Streamline Profiler は、Mali GPU と外部 DRAM(またはシステムキャッシュ)間の帯域幅を測定できます。
Arm:アセットの再チューニングをすれば最良の結果が得られますが、そのためにはコストがかかります。まずは解像度とフレームレートを下げたり、オプションのポストプロセッシングエフェクトを無効にすることから始めてみてください。
Arm:Arm Mobile Studio の Performance Advisor ツールを使用すると、Mali GPU からパフォーマンス 指標を自動的にキャプチャしてエクスポートできます。ただし、JSON 形式のレポートを生成するには Professional Edition のライセンスが必要であることにご注意ください。
Unity:Unity プロファイラーを使用すると、頂点や三角形の数など、一般的なレンダリング指標を Rendering モジュールで確認することができます。さらに、System Metrics Mali などのカスタムパッケージをプロジェクトに含めると、Unity Profiler に低レベルの Mali GPU メトリクスを追加することができます。
これを行うには GPU プロファイラーが必要です。ターゲットとするプラットフォームによって、選択すべきプロファイラーが異なります。たとえば、iOS デバイスについては、Xcode の GPU プロファイラーに Shader Profiler が含まれているので、シェーダーのパフォーマンスを行単位に分解して見ることができます。
Arm Mobile Studio は、シェーダーコードとコンピュートカーネル用の静的解析ツールである Mali Offline Compiler をサポートしています。このツールは、Arm Mali GPU ファミリの全体的な性能の見積もりと推奨事項を提供します。
チップセットが加速度的に増えていく問題は、主にデスクトッププラットフォームで懸念されるものです。家庭用ゲーム機でテストすべきハードウェアのアーキテクチャの数は限られています。モバイルでは、iOS デバイスには Apple の A シリーズ、Android には Arm や Qualcomm のさまざまなアーキテクチャがありますが、代表的なモバイルデバイスを選んで管理可能なリストに収めることは非常に簡単です。
デスクトップでは、利用可能なチップセットやアーキテクチャが多岐にわたり、テスト用に Mac や PC を購入すると高額になるため、より困難な作業となります。私たちの一番のアドバイスは、「できることをする」ということです。どんなスタジオでも、テストのための時間とお金が無限にあるわけではありません。例えば、Intel x86 CPU と同スペックの AMD プロセッサーの性能を比較しても、驚くような性能差は見られないというのが普通でしょう。最低スペックのマシンで快適に動作するのであれば、他のマシンでもそれなりに自信を持って動作すると言えるはずです。また、Unity Analytics などのアナリティクスを使用して、フレームレート、システム性能、プレイヤーのオプション設定を記録し、ホットスポットや問題のある構成を特定することも検討する価値があります。
多くのスタジオが、定期的なオンデバイスプロファイリングのために、一定レベルの自動テストを使用するようになり、チーム全体がターゲットデバイスの範囲全体でパフォーマンスを監視できるようなサマリー統計が公開されるようになってきています。よく設計されたテストシーンを使えば、これは通常、自動化に適した機械的なプロセスにすることができます。そのため、経験豊富なテクニカルアーティストや QA テスターがビルドを手動で実行する必要はありません。
そういうケースは珍しいのですが、しかし私たちはそれを目撃したことがあります。例えば、ハイエンドデバイスでは、派手なシェーダーや高解像度のテクスチャを使用するため、GPU やメモリに余計な負荷がかかるなど、プロジェクトの設定に問題があることがよくあります。ハイエンドのモバイルデバイスやコンソールは、高解像度の画面や 4K テレビ出力をセールスポイントにしていますが、深い最適化をせずにその期待に応えるだけの GPU パワーやメモリを備えているとは限りません。
現在のバージョンの C# Job System を使用する場合、ワーカースレッドの数によって変化するジョブスケジューリングのオーバーヘッドがあるかどうかを確認し、さらに CPU コアの数によって変化するジョブスケジューリングのオーバーヘッドがあるかどうかを確認します。このことが影響して、64 コア以上の Threadripper™ では、そう高性能ではない 4 コアや 8 コアの CPU よりも、コードの実行速度が遅くなることがあるのです。この問題は Unity の将来のバージョンで対処される予定ですが、それまでの間は JobsUtility.JobWorkerCount を設定して、ジョブワーカースレッドの数を制限してみてください。
フレーム予算というと、ほとんどの場合、フレーム全体の時間予算のことを指します。1000 をターゲット fps で割った値を計算し、フレーム予算を求めます。 30fps の場合は 33.33ms、60fps の場合は16.66ms、120Hz の場合は 8.33ms などとなります。モバイルの場合は、各フレームの間にチップにクールダウンの時間を与えるために、この数値を約 35% 減らします。この予算を分割して、機能別、システム別のサブ予算を計算することは、非常に特殊で予測可能なシステムを持つプロジェクトや、タイムスライスを多用するプロジェクトを除けば、おそらく過剰な行為です。
一般にプロファイリングとは、最大のボトルネック、つまり、最大のパフォーマンス向上の可能性を見つけるプロセスです。つまり、「物理演算に 1.2ms かかっているが、予算は 1ms しかない」ではなく、フレームを見て、「レンダリングに 6ms かかっており、これがフレーム内のメインスレッドの CPU コストのうち最も大きい。どうすればそれを減らせるか」と言うべきです。
ゲームの開発、発売、プロモーション、運営は、多方面に向き合う大変な仕事です。そのため、開発者にとって常に多くの優先すべき事柄があり、プロファイリングが後回しにされることがあります。やるべきことだとわかっていても、ツールに不慣れだったり、学ぶ時間がないと感じていたりするかもしれません。あるいは、パフォーマンスの最適化よりも機能の完成を優先するあまり、プロファイリングをワークフローに組み込む方法がわからないという場合もあります。
バグや技術的負債と同様に、パフォーマンスの問題は、プロジェクトの開発サイクルの後半ではなく、早い段階で対処する方がコストもリスクも低くなります。私たちは、プロファイリングのツールやテクニックをよく知らない開発者のために、その謎を解く手助けをすることに重点を置いています。プロファイリングに関する e ブックと、それに関連するブログ記事やウェビナーは、それを支援することを目的としているのです。
コーススタックの割り当てを有効にすると、マネージド割り当てを特定できる完全なコールスタック(Unity CPU プロファイラーのタイムラインビューではマゼンタで表示)を見ることができます。さらに、ProfilerMarker をコード中に散りばめることで、長時間実行されるメソッドやプロセスを手動で計測することができます(そして、計測するべきです)。現在、アプリケーションの特定の部分で自動的にディーププロファイリングを有効にしたり、プロファイリングを完全に無効にしたりする方法はありません。しかし、ProfilerMarker を手動で追加し、必要に応じてコールスタックの割り当てを有効にすることで、ディーププロファイリングに頼ることなく問題箇所を掘り下げることができます。
Unity 2022.2 からは IgnoredByDeepProfilerAttribute を使って、Unity Profilerがメソッドコールをキャプチャしないようにすることも可能です。クラス、構造体、メソッドに IgnoredByDeepProfiler 属性を追加するだけです。
ディーププロファイリングについては、プロファイラーのドキュメントで説明しています。それから、プロファイリング情報の最も詳細な情報を 1 つにまとめたリソースである e ブック「Ultimate Guide to profiling Unity games」中には、関連ドキュメントやその他のリソースに至るまで、随所にリンクが張られています。
ディーププロファイリングは、マネージド割り当ての具体的な原因を見つけるために使用できますが、割り当てコールスタックは、全体としてはより少ないオーバーヘッドで同じことを行うことができます。同時にディーププロファイリングは、特定の ProfilerMarker に時間がかかっている理由を迅速に調査するのに役立ちます。スクリプトに多数の ProfilerMarker を追加してゲームを再ビルドするよりも、これを有効にする方が便利だからです。しかし、この機能はパフォーマンスを大きく歪めるので、一般的なプロファイリングでは有効化しない方が良いとは言えるでしょう。
モバイルデバイスでは、ドライバーやハードウェアのレベルで VSync が強制的に有効になるため、Unity の品質設定でこれを無効にしても、これらのプラットフォームでは何の違いも生じないはずです。VSync を無効にすることで性能に悪影響が出るというケースは聞いたことがありません。VSync を有効にしたプロファイルのキャプチャを撮り、同じシーンで VSync を無効にして、もう一度キャプチャを撮ってみてください。その後、Profile Analyzer を使ってキャプチャを比較し、なぜそれほどパフォーマンスが異なるのかを分析してください。
これは「Ultimate guide to profiling Unity games」で扱われています。また、より詳しい情報をブログ記事「Unity フレームタイミングマネージャーによるパフォーマンスボトルネックの検出」で得ることができます。
一般的に、メインスレッドがレンダースレッドを待ち、レンダースレッドが GPU を待っていることがその兆候です。具体的なマーカー名はターゲットプラットフォームやグラフィックス API によって異なりますが、「PresentFrame」や「WaitForPresent」といった名前のマーカーを探すとよいでしょう。
メモリプロファイラーを使ってメモリスナップショットを比較し、リークをチェックします。例えば、メインメニューでスナップショットを撮り、ゲームに入り、終了してメインメニューに戻り、2 回目のスナップショットを撮るというやり方があります。この 2 つを比較することで、ゲームのオブジェクトや割り当てがまだメモリ上に残っているかどうかが分かります。
現在、多くのゲームプロジェクトで Data-Oriented Technology Stack(DOTS)の一部が利用されています。Native Containers、C# Job System、Mathematics、Burst コンパイラー はすべて完全にサポートされているパッケージで、これを今すぐ使い、最適で並列化されたハイパフォーマンス C#(HPC#)コードを記述してプロジェクトの CPU パフォーマンスを向上させることが可能です。
また数は少ないですが、Entities と、Hybrid Renderer、Unity Physics、NetCode といった関連パッケージを使用しているプロジェクトもあります。しかし、現時点では、これらのパッケージは実験的なものであり、使用するにはある程度の技術的リスクを受け入れる必要があります。このリスクは、まだ進化途中の API、まったく実装されていないかまたは不完全な機能、そして Unity の Entity Component System(ECS)を最大限に活用するためのデータ指向設計(DOD)を理解するためのエンジニアリングの学習曲線に由来しています。Unity エンジニアの Steve McGreal がDOTS のベストプラクティスのガイドを書きました。 このガイドには、DOD の基礎知識と ECS のパフォーマンスを向上させるヒントが記載されています。
レンダリングは複雑なプロセスであり、SetPass 呼び出しの最大数にハードリミットを設定したり、シェーダーの複雑さの指標を設定する実用的な方法はありません。1 種類のゲーム機だけというようにハードウェアプラットフォームが固定されていても、レンダリングしたいシーンの種類や、1 フレーム中に CPU や GPU で行われている他の作業によって、限界が変わってくるのです。
だから、プロファイリングのタイミングは「early and often」(早く、頻繁に)が鉄則なんです。開発チームは「バーティカルスライス」デモを開発の初期段階で作ることがよくあります。これは通常、最終的なゲームのビジュアルに忠実なレベルで開発された、短いゲームプレイです。これはレンダリングのプロファイリングを行い、どのような最適化や制限が必要なのかを把握する最初の機会です。プロファイリングは、新しいエリアやその他の主要なビジュアルコンテンツが追加されるたびに繰り返し行うべきです。
パフォーマンス最適化について学ぶためのその他のリソースはこちらです。
ブログ
How-to ページ
e ブック
Learn のチュートリアル
さらに高度な技術的コンテンツを近日公開予定ですが、それまでの間、フォーラムで取り上げてほしいトピックを自由に提案し、ウェビナー録画の完全な録画 をチェックしてください。