以下のマニュアルと記事を読んでのまとめ。
- Unity - Documentation - WebGLを対象とした場合に必要なメモリへの配慮
- Unity - Documentation - WebGLのパフォーマンスについて
- Unity + WebGLに関する記事
全てのコードはブラウザで実行可能なJavaScriptのasm.jsに変換される。
asm.jsは対応していないブラウザでの実行もサポートしているが、実行速度は落ちる傾向にある。
Edge、Firefoxはasm.jsをサポートしており、より高いパフォーマンスが出るとされている。
WebGLコンテンツとして実行し、Unityプロファイラが使用できる。
そのためにBuild SettingsのAutoconnect Profilerの設定が必要になる。
まず、WebGLビルドしたゲームをブラウザで動かす場合、以下の懸念点があります。
- WebGLコンテンツはブラウザ内で実行されるため、使用できるメモリはブラウザ内部のメモリ空間に限られる
- 利用できるメモリ総量は、ブラウザ、OS、デバイスによって大きく変動する
- ブラウザが34ビット、64ビットなのか?
- タブごとにプロセスが分離されるか?全てのタブで共有メモリ空間を利用するのか?
- JavaScriptエンジンのゲームコードの解析にどの程度メモリを消費するのか?
基本的にUnityから出力されたWebGLコンテンツがブラウザに要求するメモリ空間は以下のようなものがあります。
-
Unityヒープ
WebGLコンテンツが主に使用するメモリ。
ゲームオブジェクトや読み込まれているアセットやシーンを保持するメモリ領域。
WebGLコンテンツが要求するヒープメモリ量をPlayer Settingsから設定する事ができる。
コンテンツの容量を削減して、要求されるメモリ量を減らす事が理想ですが、 シーンに含まれるすべてのデータを再生できるだけの大きさが必要なため、要求メモリ量を調整する方が現実的っぽい。 -
アセットデータ
コンテンツに必要なすべてのシーンとアセットを持った.dataファイルを書き出す。
このファイルはゲームの開始前にメモリに展開され、非圧縮状態でメモリを占有する。
メモリ使用量を削減するために、アセットのビルドサイズを最適化する必要がある。
AssetBundleを使う事で、必要な時に必要なだけのアセットを読み込める。
(AssetBundleはUnityヒープに読み込まれるので、ブラウザによる追加割り当てが発生しない?どういうこと?)
ここまではコンテンツ総量によるメモリの削減についてで、
実際にゲームコードをパースするのに必要なメモリも存在する。
詳細は以下、あとで読む。
JavaScriptエンジンによって解析されるコード量を減らす
Out of memoryへの対処方法はここでは割愛する。
Out of memory. If you are the developer of this content, try allocating more memory to your WebGL build in the WebGL player settings.
- WebGLのGC管理について
- WebGLではGCはスタックが空になった場合のみ実行される
- WebGLではフレーム毎にGC割り当てが行われる
具体的にはC#で記述されたユーザーコードは以下の手順でブラウザ上で実行可能なJavaScriptに変換される。
C# => mcs
CIL => IL2CPP
C++ => Clang
LLVM-IR => Emscripten
JavaScript
IL2CPPのコンパイラオプションにあるように、
コンパイラオプションの設定によって、実行時パフォーマンスが向上する可能性もある。
- PlayerSettingsで要求メモリ量を上げる
逆に下げすぎるとOOMが必ず発生する - Strip Engine Code チェックを入れる(未使用クラスを削除する?)
もう少し詳しく調べる - できるだけアセットバンドルを使う
- JavaScriptをできるだけ小さくする(具体的にどうやる?)
Emscriptenから吐き出されるJavaScriptを小さくする事によってコード解析の負荷を下げる。