Unity を検索

モバイルゲームのパフォーマンスを最適化しよう:専門家が語る物理演算、UI、オーディオの設定に関するヒント

2021年7月13日 カテゴリ: テクノロジー | 13 分 で読めます
Creepy image of cartoon cavern illuminated by a lantern featuring skeletons and a spider.
Creepy image of cartoon cavern illuminated by a lantern featuring skeletons and a spider.

Integrated Success チームは、Unity の顧客が抱える複雑な技術的問題をサポートします。シニアソフトウェアエンジニアで構成されるこのチームに、モバイルゲームの最適化に関する知見を聞かせてもらいました。

当社の Accelerate Solutions チームはソースコードを熟知しており、無数に存在する Unity の顧客みんながエンジンを最大限に活用できるようサポートしています。このチームは、クリエイターのプロジェクトに深く入り込み、パフォーマンスを最適化することで、スピード、安定性、効率性を向上させるポイントを見つけ出します。

Unity のエンジニアたちがモバイルゲームの最適化に関する知見のシェアを始めるとすぐに、元々予定していた 1 本のブログ記事に収まりきらないほどの素晴らしい情報があることに気づきました。そこで私たちは、彼らの膨大な知識を e ブックとしてまとめ(ダウンロードはこちら)、そこに収録されている 75 以上の実用的なヒントの一部を紹介する一連のブログ記事を作成することにしました。

シリーズ 2 本目となる今回は、UI、物理演算、オーディオ設定でパフォーマンスを向上させる方法を詳しく見ていきます。前回の記事では、プロファイリング、メモリ、コードアーキテクチャについてご紹介しました。まだご覧になっていない方はぜひそちらもご覧ください。また、次回の記事ではアセット、プロジェクト設定、グラフィックスについて取り上げますので、そちらもご期待ください。 

e ブック(英語)のダウンロードはこちらからどうぞ。

それでは早速、ご紹介していきます。

物理演算

Unity のビルトインの物理演算エンジン(Nvidia PhysX)は、モバイルで使うには高価なものとなることがあります。しかし、以下のヒントを参考にすれば、1 秒あたりのフレーム数をより多くすることができます。

設定の最適化

有効ならば、プレイヤー設定Prebake Collision Meshes をチェックしましょう。

Image of the in player settings box with a dark grey background and the text "prebake collision meshes*" checked and squared off in red
Prebake Collision Meshes を有効にする。

物理演算の設定Project Settings > Physics)を編集し、Layer Collision Matrix を出来るだけ簡素にするようにしてください。 

また、Auto Sync Transforms を無効にし、Reuse Collision Callbacks を有効にしてください。

Picture of the project settings box with a grey background and the sections for "Auto Sync Transforms" and "Layer Collision Matrix" squared off in red.
物理演算のプロジェクト設定を変更することで、パフォーマンスを向上させることができる。
Image of the physics module of the profiler with the 5ms section showing activity in green, blue, and orange against a black background.
プロファイラーの Physics モジュールのパフォーマンスに問題がないか確認する。

コライダーの簡略化

メッシュコライダーは高価です。複雑なメッシュコライダーを、元の形状を近似するプリミティブのコライダーまたは簡略化されたメッシュコライダーに置き換えましょう。

Use primitives or simplified meshes for colliders.
コライダーの形状には、プリミティブまたは簡略化されたメッシュを使用しよう。

物理演算メソッドで Rigidbody を動かす

MovePositionAddForce などのクラスメソッドを使って、Rigidbody の付いたオブジェクトを動かします。オブジェクトの Transform コンポーネントを直接使って移動させると、物理演算でワールドの再計算を行う必要が生じ、複雑なシーンでは計算のコストが高くなります。物理ボディの移動は Update ではなく FixedUpdate で行いましょう。

Fixed Timestep を修正する

プロジェクト設定にある Fixed Timestep のデフォルトは 0.02(50Hz)です。これを目標とするフレームレートに合わせて変更してください(例:30fps なら 0.03)。 

実行時にフレームレートが低下する場合、これは Unity が FixedUpdate をフレームごとに複数回呼び出していることを意味し、物理演算を多用するコンテンツでは CPU パフォーマンスに問題が生じさせる可能性があります。

Maximum Allowed Timestep は、フレームレートが低下した場合に、物理演算や FixedUpdate イベントを使用できる時間を制限するものです。この値を下げると、パフォーマンスが低下したときに、物理演算やアニメーションが遅くなる可能性がありますが、同時にフレームレートへの影響も少なくなります。

Image of the fixed time module inside the project settings with a grey background and white text.
Fixed Timestep を目標とするフレームレートに合わせて変更し、Maximum Allowed Timestep を下げてパフォーマンス上の不具合を低減する。

Physics デバッガーで視覚化する

問題のあるコライダーや不具合のトラブルシューティングには、Physics Debug ウィンドウ(Window > Analysis > Physics Debugger)を使いましょう。これにより、互いに衝突する可能性のあるゲームオブジェクトが色分けされて表示されます。

Image of an orange boat with a mesh overlay and a blue shadow inside the physics debugger dialog box.
Physics Debug ツールは、物理演算の対象になるオブジェクトがどのように相互作用するかを視覚化する時に役立つ。

詳しくは、Unity ドキュメントの物理演算デバッグの可視化をご覧ください。

ユーザーインターフェイス

Unity UI(UGUI)は、しばしばパフォーマンス問題の原因となります。Canvas コンポーネントは、UI 要素のメッシュを生成・更新し、GPU にドローコールを発行します。その機能の実行コストは高くなることもあるので、UGUI を利用する際には以下のことに注意してください。

キャンバスの分割

何千もの要素を持つ大きなキャンバスがある場合、1 つの UI 要素を更新するとキャンバス全体が更新されることになり、CPU の使用率が急上昇することがあります。 

UGUI の複数のキャンバスをサポートする機能を活用しましょう。更新頻度に応じて UI 要素を分割しましょう。静的な UI 要素のキャンバスは分離して置き、同時に更新される動的な要素は小さなサブキャンバスに配置しておきます。

また、あるキャンバス内のすべての UI 要素が、同じ Z 値、マテリアル、テクスチャを持つようにしましょう。

見えない UI 要素を非表示にする

例えば、キャラクターがダメージを受けたときに表示される体力バーのように、ゲーム中に不定期にしか表示されないUI要素があります。UI 要素が見えなくてもアクティブになっていれば、ドローコールを使用している可能性があります。見えない UI コンポーネントは明示的に無効にし、必要に応じて再度有効にするようにしましょう。

キャンバスが見えないようになればいいのであれば、GameObject ではなく Canvas コンポーネントを無効にしてください。これにより、メッシュや頂点の再ビルドを避けることができます。

GraphicRaycaster を制限し、Raycast Target を無効にする。

画面上でのタッチやクリックなどの入力イベントを処理するには、GraphicRaycaster コンポーネントが必要です。これは単純に画面上の各入力ポイントをループし、それが UI の RectTransform 内にあるかどうかをチェックするものです。 

デフォルトの GraphicRaycaster をヒエラルキーの一番上にあるキャンバスから削除します。代わりに、インタラクションが必要な個別の要素(ボタン、Scroll Rect など)にのみ、GraphicRaycaster を追加します。

Image of the grey graphic raycaster dialog box with white text.
デフォルトで有効になっている Ignore Reversed Graphic も無効にする。

また、すべての UI テキストや画像について、必要なければ Raycast Target を無効にします。UI が多くの要素で構成されている複雑なものであれば、こうした小さな変更の積み重ねが無駄な計算を減らすことにつながります。

Image dialog box with a grey background and the text "Raycast Target" outlined in a red square.
必要のないところでは Raycast Target を無効にする。

レイアウトグループを避ける

レイアウトグループは非効率的に更新されるので、使用は控えめにしましょう。動的なコンテンツを扱わない場合はまったく使わないようにし、プロポーショナルレイアウトを作る際はアンカーを使用するようにしましょう。これをやりたくない場合は、カスタムコードを作成して、UI を設定した後に Layout Group コンポーネントを無効にしてください。

動的な要素にレイアウトグループ(Horizontal、Vertial、Grid)を使用する必要がある場合は、パフォーマンスを向上させるために入れ子にしないようにしてください。

Grid layout group dialog box with grey background and white text.
レイアウトグループは、特に入れ子になっている場合、パフォーマンスを低下させる場合がある。

大きなリストビューやグリッドビューを避ける

大きなリストビューやグリッドビューは高価です。大規模なリストビューやグリッドビューを作成する必要がある場合(例:数百のアイテムを含む持ち物画面)、アイテムごとに UI 要素を作成するのではなく、より小さな UI 要素のプールを作ってその中の要素を再利用することを検討してください。このサンプル GitHub プロジェクトでは、実際にそれを行っているところを見ることができます。

多数の要素を重ね合わせない

UI 要素を多数重ねる(例:カードバトルゲームでカードを重ねる)と、オーバードローになります。コードをカスタマイズして、層になった要素を実行時により少数の要素やバッチにマージすることができます。

複数の解像度とアスペクト比を使う

現在、モバイルの解像度や画面サイズはデバイスによって異なっているため、各デバイスで最高の体験を提供するために、代替バージョンの UI を作成しましょう。

デバイスシミュレーター を使用して、サポートされているさまざまなデバイスで UI をプレビューすることができます。また、XCodeAndroid Studio でもバーチャルデバイスを作成することができます。

Image of the device simulator that has a grey dialog box background and a simulation of a racing boat game on a smartphone.
デバイスシミュレーターを使って、さまざまな画面フォーマットのプレビューを行う。

フルスクリーン UI を使うときは、他のものをすべて非表示にする

一時停止画面やスタート画面で、シーンのそれ以外の部分がすべて隠れてしまう場合は、3D シーンをレンダリングしているカメラを無効にしてください。同様に、一番上のキャンバスの後ろに隠れている背景のキャンバス要素も無効にします。

この時、60fps で更新する必要はないはずなので、フルスクリーン UI を表示している間は、Application.targetFrameRate を下げることも検討してください。

ワールド空間とカメラ空間のキャンバスにカメラを割り当てる

EventRender Camera フィールドを空白にしておくと、Unity はそこに Camera.main を強制的に割り当てます。これは描画コストを不必要に増大させます。 

キャンバスの Render ModeScreen Space - Overlay を使えば、カメラは必要なくなります。これを使うことも検討してください。

Image of the Camera space canvases dialog box with a greyed out background and white text.
Render Mode に World Space を指定する場合は、必ず Event Camera に何か値を入れる。

オーディオ

オーディオは通常、パフォーマンスのボトルネックにはなりませんが、ここも最適化してメモリを節約することができます。

Inspector dialog box with grey background and white text with an orange voice modulator at the bottom.
オーディオクリップの読み込み設定を最適化する。

可能な場合は、オリジナルの非圧縮 WAV ファイルをソースアセットとして使用する

圧縮されたフォーマット(MP3 や Vorbis など)を使うと、Unity はそれを一旦展開し、ビルド時に再圧縮します。この結果、品質を低下させる部分が 2 つできることになり、最終的な品質が低下します。

クリップを圧縮し、圧縮ビットレートを下げる

圧縮することで、クリップのサイズとメモリ使用量を削減することができます。

  • 大多数のサウンドには Vorbis を使用するとよいでしょう(ループさせないサウンドには MP3)。
  • 頻繁に使われる短い音(足音、銃声など)には、ADPCM を使用してください。これは非圧縮の PCM に比べてファイルサイズを小さくしつつ、再生時のデコードも速いのが特徴です。

モバイル機器での効果音は、最大でも 22,050Hz とします。これより低い値に設定しても、最終的な品質への影響はほとんどありませんが、これはご自身の耳で聴いて判断してください。

適切な Load Type の選択

クリップサイズによって設定が異なります。

  • 小さなクリップ(200k バイト未満):Decompress on Load を選びましょう。これは、サウンドを raw 16 ビット PCM オーディオデータに展開し CPU コストとメモリを消費するため、短いサウンドのみに使うべきものです。
  • 中くらいのクリップ(200k バイト以上):Compressed in Memory にしましょう。
  • 大容量ファイル(BGM):Streaming に設定します。こうしないと、アセット全体が一度にメモリに読み込まれ、メモリを使いつくしてしまいます。

ミュートされた AudioSource をメモリからアンロードする

ミュートボタンを実装する際には、単に音量を 0 にするだけでなく、AudioSource コンポーネントを破棄して、メモリからアンロードすることができます。ただし、プレイヤーがミュート状態を頻繁に切り替える必要がない場合に限ります。

モバイルゲームのパフォーマンス向上のヒントのリスト全体をダウンロードする

次回のブログでは、グラフィックとアセットについてご紹介します。今すぐチームからのヒントとコツをすべて乗せたリスト全体を見てみたい方は、こちらのページから完全版の e ブックをダウンロードしてご覧ください。

Image of the ebook cover with red background and a graphic of an adventure game with a dragon and the words "Optimize your mobile game performance" in bold white text.

e ブック(英語)をダウンロードする

Integrated Support サービスについてもっと知りたい、あるいはチームにエンジニアと直接やりとりする窓口や、専門家のアドバイスやプロジェクトのベストプラクティスガイダンスを提供したいとお考えの方は、こちらのページでご案内している Unity のサクセスプランをご検討ください。

今後もパフォーマンス向上のためのヒントをお届けしていきますので、ぜひご期待ください。

私たちは皆さんの Unity アプリケーションに最大限のパフォーマンスを発揮させるお手伝いをしたいと考えています。他にも取り上げてほしい最適化に関わるトピックがありましたら、コメントセクションでお知らせください。

2021年7月13日 カテゴリ: テクノロジー | 13 分 で読めます
関連する投稿