
Unity のタイルマップによる 2D ゲームのパフォーマンスの最適化
これらのヒントは、Unity の 2D ツールセットの使用経験があるユーザーに最適です。Unity を使用して商用 2D ゲームを開発するプロのクリエイターにとって、もう 1 つの優れたリソースは、当社の電子書籍 「2D ゲームアート、ライティング、アニメーション」です。
Unity で 2D ゲームを開発するのが初めての場合は、 新規ユーザー向けの 2D ガイドから始めてください。

パフォーマンスに関する一般的なヒント
考慮すべき一般的なパフォーマンスのヒントをいくつか紹介します。
- アセット(データ)のパフォーマンスについては、最初から考えるようにします。これらの要素のパフォーマンスが低いと、コードの最適化のために後でできることは限られてしまいます。
- 利用可能な最も低価格のターゲット デバイスでプロファイルを作成します。プロジェクト開発全体を通じて、iOS デバイス用の Xcode などのプラットフォーム固有のプロファイリング ツールとともに Unity Profiler を使用します。
- 最も低スペックのターゲット デバイスでは、使用可能な RAM の 3 分の 1 以上を使用しないでください。これにより、コンテンツがさまざまなモバイル デバイスで適切に実行されることが保証されます (安価な Android スマートフォンは、モバイル市場全体で引き続き最も人気があります)。
2D 最適化のヒントについては、次のリソースを参照してください。

タイルマップの簡単な紹介
Tilemap コンポーネントを使用すると、グリッド オーバーレイ上のタイルを使用して 2D レベルを効率的に作成できます。これには、次のようないくつかの要素が含まれます。
スプライトとゲームオブジェクトの組み合わせを使用して 2D レベルを作成し、ソート レイヤー、タイルマップ コライダー、アニメーション タイルなどのプロパティを制御できます。正方形、 六角形、 等角投影のスプライトをペイントすることもできます。
レベルをタイルマップでペイントすると、タイルマップ ゲームオブジェクトに適用されたときに、タイルマップ コライダー 2D コンポーネントによってタイルの周囲にコライダーが自動生成されます (タイルのコライダー タイプ設定に基づきます)。
スプライトで構築されたシーンと比較して、タイルマップで得られるパフォーマンスの向上を見てみましょう。

ゲームオブジェクトが少なくなる
Tilemap を使用すると、読み込み時間が短縮され、メモリと CPU の使用量が削減されます。
以前に 2D ゲームやアプリを開発したことがある方であれば、ゲーム内に莫大な量のスプライトが作成されてしまった経験があると思います。そういったスプライトはすべて別個のゲームオブジェクトとして扱われます。これらの Sprite GameObject にはそれぞれ、Transform や Renderer などのコンポーネントがあり、これらはすべてメモリを消費します。その他 Collider などのコンポーネントについては、CPU のオーバーヘッドを引き起こしてしまいます。
対照的に、タイルマップは 1 つのレンダラーをマップ全体およびその中のすべてのタイルで使用します。これにより、その固有のデータ構造のみが処理されるため、メモリ全体を通して複数のデータ構造が存在するよりもオーバーヘッドが少なくなります。
GameObject の数が少ないと階層が整理され、必要なものを探すために複雑なリストをスクロールする必要がなくなります。

シーンのサイズが小さくなる
Unity タイルマップはシーンのサイズを縮小します。GameObject とコンポーネントの数が少ないということは、実行時にディスクから読み込み、逆シリアル化し、メモリに保持するオブジェクトが少なくなることを意味します。
Unity でのシーンの読み込みは、2 つの部分からなるプロセスです。まず、ディスクからデータが読み取られます。これは、特に Android デバイスでは、ゲームで最も時間がかかるプロセスです。次に、データがデシリアル化されます。デシリアライゼーションは、データをある形式から別の形式に変換するプロセスです。本質的には、保存された状態からデータとオブジェクトを復元します。シリアライズは、シーンファイルをエディターにロードするときはいつでも Unity 内部で行われ、実行時にそれらの保存されたファイルを Unity のオブジェクトに変換します。
上の画像では、シリアル化された 2 つのシーン ファイル (1 つはタイルマップを使用し、もう 1 つはスプライトを使用して再作成されたもの) の比較を確認できます。ゲーム Robbie Swifthandのこのシーンを提供してくれた Pixel Reign に感謝します。
右側はシリアライズされたタイルマップによるセクションを表し、4 つのファイルで構成されています。使用されるタイルの種類を含むすべてのタイルのルールは、タイルマップの上部に設定されます。先行する各タイルは、使用されるタイルとその位置などのプロパティを示します。
左側には、Transform および Sprite Renderer コンポーネントを含む 1 つの Sprite があります。
この比較から、Sprite のシリアル化にどれだけの作業が必要かが明らかです。特に、スプライトを使用するシーンのファイルには 370,000 行がありますが、タイルマップを使用するシーンには 30,000 行しかありません。プロジェクトとリポジトリのサイズが小さくなると、反復時間が短縮され、ワークフローがスムーズになります。
独自のシーンをテキスト ファイルとして表示する場合は、 エディター設定に移動し、 アセット シリアル化モードをオンにして、Force Textをクリックし、.unity シーン ファイルをテキスト エディターで開きます。

コライダーが少なくなる
Tilemap Collider 2D と Composite Collider を組み合わせることができます。これにより、コライダーとスプライトの数が減るだけでなく、変更を加えるたびに複雑な衝突形状を再構築する必要がなくなるため、制作の効率も向上します。Composite Collider がそれを処理します。

レンダリングのオーバーヘッドが減る
前述のように、各スプライトにはスプライト レンダラー コンポーネントがあり、レンダラーの数が増えると、カリングの準備やレンダリングのクリーンアップにかかる時間など、CPU の作業量が増えます。タイルマップを使用することで、Renderer コンポーネントの数が減り、CPU での処理が少なくなります。
カリングにかかるコストが減る
シーン内にカメラが複数ある場合、レンダラーの数も増えます。これにより、淘汰コストが増加します。
カメラ ビューでは、カリングにはレンダラーごと、カメラごとのコストがかかります。各カメラはシーン内のすべてのレンダラー コンポーネントに対してカリング チェックを実行する必要があるため、ゲームに複数のカメラを設定している場合は、タイルマップを使用するとそのコストを削減できます。

バッチの呼び出し回数が減る
バッチングとは、別の SetPass 呼び出しを行うことなく描画できるすべてのジオメトリを収集する技術のことです。タイルマップ レンダラーは、スプライトの位置に基づいてスプライトのジオメトリをバッチ処理します。その結果、タイルマップレンダラーはより多くのジオメトリでより少ないメッシュをレンダーパイプラインに送信します。それに対して、SpriteRenderer はより少ないジオメトリでより多くのメッシュを送信します。次のセクションの表に示すように、タイルマップベースのシーンではバッチ数が大幅に少なくなります。
バッチングは、「Game」ビューの「Stats」パネルで確認できます。フレーム デバッガーを 使用して、アイテムがバッチ処理されない理由を特定することもできます。

より速いフレームレート
60 fps に到達するには、各フレームのレンダリングに最大 16 ミリ秒かかります。サンプルシーンを古い iPhone 7 でプロファイリングしたところ、スプライトベースのバージョンではフレームあたり 244 ミリ秒でしたが、タイルマップ バージョンではフレームあたり 13 ミリ秒でした。
最後に、スプライトベースのシーンでの RAM 使用量は 1.1 GB でしたが、これはたとえばローエンドの Android スマートフォンにとっては多すぎます。タイルマップベースのシーンでは、RAM の使用はたった 21 MB で済むので、幅広いモバイル端末に適した動作になります。
上記の比較では、2 つのシーン間のパフォーマンスの明確な違いが示されています。

Sprite Atlasでスプライトをパックする
Sprite Atlas は 、スプライトをテクスチャにパックしてメモリ使用量と描画呼び出しを最適化できるエディター ツールです。タイルマップ内で使用されるすべてのスプライトを含むスプライト アトラス アセットを作成し、タイルマップ レンダラーによって 1 回の描画呼び出しでそれらをバッチ処理できるようにします (すべてのスプライトが 1 つのテクスチャに収まる限り)。
2Dゲームクリエイター向けのリソース
2D のスキルをレベルアップする当社のブログ読書リストには、2D ゲーム開発に役立つヒントが掲載されています。
アーティストのための 2D ゲームアート、アニメーション、ライティングこの無料の電子書籍では、Unity の 2D ツールセットを最大限に活用するためのベストプラクティスを紹介します。
2Dツールの概要:Unity が 2D 開発者に提供する機能についての便利な概要をご覧ください。
タイルマップを使用した手続き型パターン - パート I と パート II:手続き型生成によりゲームに多様性を追加します。この記事では、タイルマップや RuleTile で使用できるいくつかのアルゴリズムについて説明します。