【Defold】ゲームの最適化について
Defold Engine の最適化に関するドキュメント Optimizing a Defold game をシンプルに読みました。また、この投稿はモバイル端末向けの内容が多いです。
目次
アプリケーションサイズの最適化
Defold は Unity の様にビルの際に依存関係ツリーを作成します。ビルドシステムは、game.project に指定された起動時の Collection から開始し、参照される全てのCollection、GameObject、Component を捜査してビルドに含めるアセットリストを構築します。
※2017年の調査によると、"APKのサイズが6MB増えるごとに、インストール変換率が1%低下する “ことが示されているらしい。
アプリサイズを小さくすることはとても重要。詳細を把握するためにビルドレポートを出力することが出来ます。
エンジンの小型化
アプリケーションのマニフェストファイルを使用して、不要なエンジンコンポーネントを削除できます。例えばゲームで物理を使用しない場合は、デフォルトで含まれている物理コンポーネントを削除することが出来ます。アプリケーション マニフェストを生成するには、マニフェスト オンライン ツールを使用します。
サウンドの最適化
Defoldは.oggと.wavファイルをサポートしており、.oggは一般的に音楽に、.wavはサウンドエフェクトに使用されます。サウンドはサンプリングレート44100の16ビットであって欲しいので、エンコードする前に最適化を行う必要があります。
外部のエディターを使用して良い感じに調整して欲しいってことかな?
グラフィックスの最適化
まず最初にアトラスやタイルソースに使用されるグラフィック素材のサイズ確認をすることが重要です。ゲームで実際に必要なサイズよりも大きなサイズのグラフィックを使用してはいけません。大きな画像をインポートして適切なサイズに縮小するのはテクスチャっ目織の無駄遣いであり避けた方がいい。また、使用できるアトラスの最大サイズは、プラットフォームはハードウェアによって異なります。
HTML5 の最大テクスチャサイズ
https://webglstats.com/webgl/parameter/MAX_TEXTURE_SIZE
- iOS
- iPad: 2048×2048
- iPad 2: 4096×4096
- iPhone 6s 4096×4096
- Android
- デバイスの種類が多すぎるが大体 4096×4096.
アトラスが大きすぎる場合は、アトラスを分ける方法の他にテクスチャプロファイルを使用してテクスチャ全体を拡大縮小できます。Defoldのテクスチャプロファイルシステムでは、アトラス全体を拡大縮小するだけでなく、圧縮アルゴリズムを適用してディスク上のアトラスのサイズを縮小することができます。
テクスチャの最適化と管理方法については Texture Management in Defold – The Defoldmine – Defold game engine forum の投稿に詳しく載っています。
オンデマンドでダウンロードできるコンテンツを除外
初期のアプリケーションサイズを縮小する一つの方法として、アプリケーションバンドルからゲームコンテンツの一部を除外し、そのコンテンツをオンデマンドでダウンロードできるようにすることです。除外するコンテンツは、レベル全体からアンロック可能なキャラクター、スキン、武器、乗り物に至るまで、何でも構いません。Defoldでは、ライブアップデートと呼ばれる、オンデマンドでダウンロードできるコンテンツを除外するためのシステムを提供しています。詳しくは、ライブアップデートのマニュアルをご覧ください。
Unity のアセットバンドルがそれに近い。
Android特有のサイズの最適化
Android のビルドは、32 ビットと 64 ビットの両方の CPU アーキテクチャをサポートしていますが、Android用にビルドする際に、どのCPUアーキテクチャを含めるかを指定することができます。ここで例えば64ビットCPU アーキテクチャのみを選択するとアプリサイズを小さく出来ます。
Google Playでは、ゲームのリリースごとに複数のAPKをサポートしているため、CPUアーキテクチャごとに1つずつ2つのAPKを生成し、両方をGoogle Playにアップロードすることで、アプリケーションのサイズを小さくすることができます。
これは知らない人が結構いると思います。数年前に運営していた Unity 製のアプリは分けずにリリースされていました。そのためアプリサイズが大きかった。
アプリケーション最適化
ゲームの動作を安定させるためには、まずどこがボトルネックなのかを調べる事が大切です。レンダリングなのか、ロジックなのか?etc..。Defold 内臓のプロファイリングツールがあります。オンスクリーンまたはウェブプロファイラを使用してゲームのパフォーマンスをサンプリングし、最適化項目を洗い出すことができます。
スクリプト実行時間の短縮
プロファイラで確認した時にスクリプトのスコープ割合が高い場合は、スクリプトの実行時間を短縮する必要があります。一般的な経験則として、もちろんフレームごとに可能な限り少ないコードを実行するようにしてください。フレームごとに update() や on_input() で多くのコードを実行すると、特にローエンドのデバイスではゲームのパフォーマンスに影響を与える可能性があります。いくつかのガイドラインがあります。
毎フレームの処理を避ける
ユーザー入力以外の目的で、update や on_input でポーリングする様な処理を書かない様にしましょう。
ガベージコレクションを減らす
Lua テーブルなど短命なオブジェクトをフレームごとに作成する様なことは避けましょう。可能な限りテーブルは再利用する形にしよう。
message や action のid は事前にキャッシュする
なんども参照するid 類は 事前にキャッシュしておきましょう。
毎回 hash 値を得る
function on_message(self, message_id, message, sender)
if message_id == hash("message1") then
msg.post(sender, hash("message3"))
elseif message_id == hash("message2") then
msg.post(sender, hash("message4"))
end
end
事前にキャッシュしておく
local MESSAGE1 = hash("message1")
local MESSAGE2 = hash("message2")
local MESSAGE3 = hash("message3")
local MESSAGE4 = hash("message4")
function on_message(self, message_id, message, sender)
if message_id == MESSAGE1 then
msg.post(sender, MESSAGE3)
elseif message_id == MESSAGE2 then
msg.post(sender, MESSAGE4)
end
end
URL を優先的にキャッシュする
メッセージの受け渡しや他の方法でゲームオブジェクトやコンポーネントをアドレス指定するには、文字列やハッシュ、またはURLとしてIDを提供することで行うことができます。文字列やハッシュが使用されている場合は、内部的にURLに変換されます。したがって、システムの最高のパフォーマンスを得るために、頻繁に使用されるURLをキャッシュすることがお勧め。例えば
local pos = go.get_position("enemy")
local pos = go.get_position(hash("enemy"))
local pos = go.get_position(msg.url("enemy"))
3 つのケースでは、id enemy を持つゲームオブジェクトの位置を取得しています。最初と2番目のケースでは、id (文字列またはハッシュ) は使用される前に URL に変換されます。これは、URLをキャッシュして、キャッシュされたバージョンを使用した方が最高のパフォーマンスを発揮することを教えてくれます。つまり、事前にURLをキャッシュしたものを参照する方法が最もパフォーマンスが出ます。
function init(self)
self.enemy_url = msg.url("enemy")
end
function update(self, dt)
local pos = go.get_position(self.enemy_url)
end
レンダリング時間の短縮
描画コールの削減
描画コールの削減についての詳細は、https://forum.defold.com/t/draw-calls-and-defold/4674 の投稿が参考になります。
オーバードローを減らす
シェーダの複雑さを減らす – GLSLの最適化については、このKronosの記事を読むのもひとつです。また、Defoldが使用するデフォルトのビルトインシェーダを変更して、シェーダの精度を下げて、ローエンドデバイスの速度を上げることもできます。すべてのシェーダは高精度を使用しており、例えば Mediump に変更することでパフォーマンスが若干向上する場合があります。
シーングラフの複雑さを軽減
プロファイラがGameObjectスコープ、特にUpdateTransformサンプルで高い値を示す場合は、シーングラフの複雑さを軽減する必要があります。
カリング等すると良い。
その他
メモリの最適化
バッテリー使用量の最適化
- フレームごとにコードを実行しない
- 加速度計を無効化する
- メモリの最適化と同様に プロファイリング する。
まとめ
自動翻訳を駆使してシンプルにですが読んでみました。意味がわかると基本的な事が書かれていることが分かりますね。途中に出てきたライブアップデートなど、まだ試していないものがあるので今後試してみたいなと思います。