最終更新:2020 年 2 月(読み終わるまでの時間:10 分)

Unity のタイルマップによる 2D ゲームのパフォーマンスの最適化

このページで学ぶ内容:Unity のタイルマップを使用して、2D のゲームとアプリのパフォーマンスを改善するためのヒント。対象となるパフォーマンス領域として、シーンのサイズ、シリアル化、レンダラーのオーバーヘッド、バッチングなどがあります。 

これらのヒントは、Unity の 2D ツールセットの使用経験のある方に最適です。Unity で 2D ゲームを開発するのが初めての方は、新規ユーザー向け 2D ガイドから始めることをお勧めします。 

パフォーマンスに関する一般的なヒント

タイルマップがどのようにパフォーマンスを改善するかを見ていく前に、全般的に使えるテクニックを紹介します。  

アセット(データ)のパフォーマンスについては、最初から考えるようにします。これらの要素のパフォーマンスが低いと、コードの最適化のために後でできることは限られてしまいます。 

利用を想定している最低限のデバイスをプロファイリングします。プロジェクト開発全体にわたって、Xcode で利用できる無料のプロファイリングツールと共に Unity プロファイラーを使用します。  

想定するデバイスの中で最もローエンドなもので利用できる RAM の 1/3 以上は使用しないでください。これにより、幅広いモバイル端末でコンテンツを確実に実行できます(市場全体で継続して人気が高いのは安価な Android スマートフォンです)。 

最後に、各アプリストアで指定されているアプリサイズの制限を考慮に入れることを忘れずに。 

Unity はモバイルデベロッパー向けの最適化のノウハウを多数用意しています。すでにこれらのガイドをご存じかもしれませんが、念のためこちらに簡単にまとめています。

Unity - タイルマップでプラットフォーマーの 2D のレベルを作成する

タイルマップ入門

Unity の 2D タイルマップ機能を使用すると、タイルやグリッドオーバーレイを使用して 2D のステージを簡単に作成できます。次のシステムが連動することで構成されています。

  • タイル
  • アセット
  • グリッドのゲームオブジェクト
  • タイルマップパレット
  • カスタムブラシ

スプライトとゲームオブジェクトを組み合わせて 2D のステージをすぐにレイアウトして作成できるほか、レイヤーの並び順、タイルマップのコライダー、アニメーション付きのタイルなどのプロパティも制御できます。タイルマップで正方形、六角形、等角投影型のスプライトをペイントできます。 

タイルマップのワークフローは非常に効率的です。レベルのペイントを簡単に行えるほか、Tilemap Collider 2D コンポーネントをタイルマップのオブジェクトに適用することで、(タイルのコライダーの種類の設定に基づいて)タイルの周囲のコライダーを自動で生成できます。 

次のセクションでは、スプライトで構築されたシーンと比較したタイルマップのパフォーマンスの改善点を紹介します。

ゲームオブジェクトが少なくなる

これにより、ロード時間、メモリ使用率、CPU 使用率が下がります。

以前に 2D ゲームやアプリを開発したことがある方であれば、ゲーム内に莫大な量のスプライトが作成されてしまった経験があると思います。そういったスプライトはすべて別個のゲームオブジェクトとして扱われます。スプライトのゲームオブジェクトにはそれぞれ Transform や Renderer など、いわゆるコンポーネントが存在し、それぞれがすべてメモリを消費しています。その他 Collider などのコンポーネントについては、CPU のオーバーヘッドを引き起こしてしまいます。

対照的に、タイルマップは 1 つのレンダラーをマップ全体およびその中のすべてのタイルで使用します。これにより、その固有のデータ構造のみが処理されるため、メモリ全体を通して複数のデータ構造が存在するよりもオーバーヘッドが少なくなります。 

ゲームオブジェクトの数が少なくなることで、ヒエラルキーも簡潔になり、必要なものを探すのに複雑なリストをスクロールする必要がなくなります。

Unity - タイルマップにより小さくなったシーンのサイズ

シーンのサイズが小さくなる

ゲームオブジェクトとコンポーネントが少なくなることで、ディスクからロードする、デシリアライズする、および実行時にメモリに保持するオブジェクトが少なくなるため、シーンのサイズが小さくなります。 

Unity でのシーンのロードは、2 つのプロセスに分けて行われます。まず、ディスクからデータが読み取られます(ゲーム内、特に Android デバイスで最も時間がかかることが多いプロセスです)。次に、デシリアライズされます。 

デシリアライズは、データを 1 つの形式から別の形式に変換するプロセスです。基本的に、データやオブジェクトを保存された状態から復元します。シリアライズは、シーンファイルをエディターにロードするときはいつでも Unity 内部で行われ、実行時にそれらの保存されたファイルを Unity のオブジェクトに変換します。次のセクションでは、シリアライズされた 2 つのシーンファイルの比較を示します。

上の画像は、シリアライズされた 2 つのシーンファイルの比較を示します。一方はタイルマップを使用し、もう一方はスプライトを使用して再作成されています(Pixel Reign が制作したゲーム『Robbie Swifthand』からのシーンの抜粋です)。

右側はシリアライズされたタイルマップによるセクションを表し、4 つのファイルで構成されています。すべてのタイルに適用されるルール(使用されるタイルの種類など)は、タイルマップの最上部で設定されています。後続のタイルはそれぞれ、使用されるタイルやその位置などの状態プロパティを示します。

左側はスプライトのゲームオブジェクトを表し、Transform コンポーネントと SpriteRenderer コンポーネントがあります。 

この比較から分かるように、スプライトのシリアライズにはかなり多くの処理を必要とします。スプライトを使用したシーンでは、ファイルに 370,000 行もあるのに対し、タイルマップを使用したシーンは 30,000 行で済みます。全体的にプロジェクトやリポジトリのサイズが小さくなり、反復時間の短縮とワークフローの改善につながります。

ちょっとしたテクニックを紹介します。「Editor Settings」で「Asset Serialization」の「Mode」を「Force Text」に設定し、テキストエディターで .unity シーンファイルを開くことで、シーンをテキストファイルとして表示できます。

Unity - タイルマップによりコライダーが少なくなる

コライダーが少なくなる

タイルマップのコライダーを複合コライダーと連携させることができます。これにより、コライダーとスプライトの数が少なくなるだけでなく、複合コライダーにより、変更を加えるたびに複雑な衝突形状を再構築する必要がなくなるため、より効率的に制作できます。

レンダリングのオーバーヘッドが減る

この記事の前半で述べたように、各スプライトには SpriteRenderer コンポーネントがあり、レンダラーの数が多ければ多いほど、カリングの準備に要する時間やレンダリングのクリーンアップなど、CPU での処理が多くなります。タイルマップを使用することで、Renderer コンポーネントの数が減り、CPU での処理が少なくなります。 

カリングにかかるコストが減る

シーン内にカメラが複数あると、レンダラーの数が多くなり、カリングのコストが増えます。カメラのビューでは、レンダラーごと、カメラごとにカリングのコストがかかります。すべてのカメラはシーン内のすべてのレンダラーに対してカリングのチェックを行う必要があるため、ゲーム内に複数のカメラのセットアップがある場合、タイルマップを使用することでそのコストを減らすのに役立ちます。

バッチ呼び出し回数減少

バッチの呼び出し回数が減る

バッチングとは、別の SetPass 呼び出しを行うことなく描画できるすべてのジオメトリを収集する技術のことです。TilemapRenderer はスプライトのジオメトリを位置に基づいてバッチ処理します。その結果、タイルマップレンダラーはより多くのジオメトリでより少ないメッシュをレンダーパイプラインに送信します。それに対して、SpriteRenderer はより少ないジオメトリでより多くのメッシュを送信します。下のテーブルに示すように、タイルマップベースのシーンではバッチ数がはるかに少なくなります。 

バッチングは、「Game」ビューの「Stats」パネルで確認できます。また、フレームデバッガーを使用してアイテムがバッチングされていない理由を特定することもできます。 

フレームレートを速める

60 FPS に到達するには、各フレームのレンダリングに要する時間を 16 ミリ秒に抑える必要があります。サンプルシーンを iPhone 7 でプロファイリングすると、スプライトベースのバージョンでは 1 フレームにつき 244 ミリ秒かかっていました。タイルマップのバージョンでは 1 フレームにつき 13 ミリ秒です。 

最後に、スプライトベースのシーンでは RAM 使用率が 1.1 GB でした。これはローエンドの Android スマートフォンなどでは高すぎます。タイルマップベースのシーンでは、RAM の使用はたった 21 MB で済むので、幅広いモバイル端末に適した動作になります。  

こちらの比較表に 2 つのシーンのパフォーマンスの明確な違いを示します。

スプライトを使用した Unity のシーン タイルマップを使用した Unity のシーン
シーンファイル:
370,000 行
シーンファイル:
30,000 行
シーンのサイズ:10 MB シーンのサイズ:831 KB
バッチ数:1930 バッチ数:157
1 フレーム:244 ミリ秒 1 フレーム:13 ミリ秒
RAM 使用率:1.1 GB RAM 使用率:21 MB

2D ゲーム開発者へのお役立ち情報

『Lost Crypt』制作の舞台裏:新しい 2D サンプルプロジェクトのアート『Lost Crypt』は、Unity のすべての 2D ツールが連携する様子を示すための 2D サンプルプロジェクトです。この横スクロールのデモゲームは Unity 2019.3 ベータ版で制作されており、ユニバーサルレンダーパイプラインを使用しています。

2D Animation 入門:2D Animation パッケージとツールを使用して、Unity で 2D キャラクターを短時間でリギングおよびアニメーション化する方法について説明するドキュメント。

2D Lights:色、輝度、減衰、ブレンディングエフェクトなど、簡単に設定できるパラメーターが用意されているさまざまな種類のライティング機能で 2D ビジュアルの質を高めます。

2D Inverse Kinematics の使用を開始する:インバースキネマティクスの背景にある考え方は、ボーンチェーンのトランスフォームという形を取り、最後のボーンが指定されたターゲット位置にできるだけ近くなるように、アルゴリズムを使用して各トランスフォームを移動することです。このドキュメントでは、それを設定する方法について説明します。 

2D アートアセットの解像度の選択:Unity ではオブジェクトのサイズをピクセルで表さないので、2D ゲーム用のアセットを作成しているアーティストにとって、どれくらいのサイズにする必要があるかについては、混乱を招く可能性があります。一般的にはゲーム開発において、こういった質問に対する回答は、「状況によって変わる」となります。この記事では、その判断をより簡単にするためのコンセプトをいくつか紹介します。

2D 用 Cinemachine:ヒントとコツ:このブログ記事では、Cinemachine カメラシステムを最大限活用し、2D ゲーム開発のスピードを大幅に高めるためのヒントを紹介します。Cinemachine Virtual Camera、Confiner などについて、特に 2D ゲーム開発と関わる部分について取り上げます。

2D 世界の構築、アニメーションおよびグラフィックスに関わる機能:ロサンゼルスで開催された Unite 2018 のこのセッションでは、Sprite Shape を使用したオーガニックな世界の構築のほか、グリッドベースレイアウトにおけるタイルマップの改善について取り上げています。Unity の 2D Animation 用の 2D スプライトリギングツールや、Pixel Perfect Camera などの 2D グラフィックスの改善点に関するデモが含まれています。 

タイルマップで使用できるプロシージャルパターン:パート 1 & パート 2:多くのクリエイターがプロシージャル生成を使用してゲームにバリエーションを追加した経験があると思います。この記事では、タイルマップや RuleTile で使用できるいくつかのアルゴリズムについて説明します。

SVG(Scalable Vector Graphics)Importer:SVG ファイルをプロジェクトに直接インポートします。SVG Importer を使用すると、どの解像度でも画質を保持しながら、非常に小さいファイルサイズのスプライトアセットを作成できます。

スプライトリギングのワークフロー:Unity で 2D アニメーションを作成するために役立つスプライトリギングのワークフローの概要について説明します。このビデオでは、Unity の Rus Scammell が付属のツールやコンポーネントを使用して強力な反復ループを作成し、2D のキャラクターや世界に命を吹き込む様子を紹介します。

 

弊社のウェブサイトは最善のユーザー体験をお届けするためにクッキーを使用しています。詳細については、クッキーポリシーのページをご覧ください。

OK