Version: 2022.2
言語: 日本語
WebGL native plug-ins for Emscripten
Cache behavior in WebGL

WebGL のメモリ

Unity WebGLではメモリの制約により、実行できるコンテンツの複雑さが制限されることがあります。

WebGL コンテンツはブラウザー上で動作します。ブラウザーは、アプリケーションがコンテンツを実行するために必要なメモリを、そのメモリスペースに確保します。 利用可能なメモリの量は、以下の条件によって異なります。

  • The device you use
  • The operating system you use
  • The browser you use, and whether it runs on a 32 or 64 processor
  • ブラウザーの JavaScript エンジンがコードを解析するのに必要なメモリ量
  • ブラウザーがタブごとに別々のプロセスを使用するかどうか、コンテンツが他のすべての開いているタブとメモリスペースを共有する必要があるかどうか。

Unity WebGL コンテンツがブラウザーに著しく大きなメモリの割り当てを必要とするエリアが、複数あります。

Unity のヒープ

Unity uses a memory heap to store all Unity engine runtime objects. These include managed and native objects, loaded Assets, Scenes, and shaders. This is like the memory that Unity Players use on any other platform.

Unity のヒープは、割り当てられたメモリの連続したブロックです。Unity は、アプリケーションのニーズに合わせて、ヒープの自動サイズ変更をサポートしています。ヒープサイズは、アプリケーションが実行すると拡張され、最大 2GB まで拡張できます。Unity はこのメモリヒープを Memory オブジェクト として作成します。Memory オブジェクトの buffer プロパティはサイズ変更可能な ArrayBuffer で、WebAssembly コードがアクセスするメモリの生のバイトを保持します。

Automatic resizing of the heap can cause your application to crash if the browser fails to allocate a contiguous memory block in the address space. For this reason, it’s important to keep the Unity heap size as small as possible. Therefore, be mindful when you are planning the memory usage of your application. If you want to test the size of your Unity heap, you can use the Profiler to profile the contents of the memory block.

You can control the initial size and growth of the heap by the memory growth options in the WebGL Player Settings. The default options are configured to work well for all desktop use cases. However, for mobile browsers you need to use the advanced tuning options. For mobile browsers, it’s recommended to configure the Initial Memory Size to the typical heap usage of the application.

アセットデータ

When you create a Unity WebGL build, Unity generates a .data file. This contains all the Scenes and Assets the application needs to launch. Because Unity WebGL doesn’tt have access to the real file system, it creates a virtual memory file system, and the browser unpacks the .data file here. The Emscipten framework (JavaScript) allocates this memory file system in the browser memory space. While your content runs, the browser memory keeps the uncompressed data. To keep both download times and memory usage low, try to keep this uncompressed data as small as possible.

To reduce memory use, you can pack your Asset data into AssetBundles. AssetBundles allow you full control over your Asset downloads. This means that you can control when your application downloads an Asset, and when the runtime unloads it. Unloading unused Assets frees up memory.

AssetBundles は、Unity のヒープに直接ダウンロードします。そのため、ブラウザーが余分な割り当てをすることはありません。

データキャッシング を有効にして、ユーザーのマシンにコンテンツのアセットデータをキャッシュします。これにより、後の実行時にそのデータを再ダウンロードする必要がなくなります。Unity WebGL ローダーは、IndexedDB API を使用してデータキャッシングを実装しています。このオプションにより、ブラウザーがネイティブにキャッシュできないサイズのファイルをキャッシュすることができます。

Data caching enables the browser to store application data on the user’s machine. Browsers often limit the amount you can store in their cache and the maximum file size that can be cached. This is often not enough for an application to run smoothly. Therefore, the Unity WebGL loader implements Date Caching with the IndexedDB API. Instead of storing the content in the browser cache, Unity stores the data in the IndexedDB.

データキャッシングオプションを有効にするには、File > Build Settings > Player Settings > Publishing Settings の順に移動します。

<!–

Large-Allocation Http ヘッダー

Your server can emit the Large-Allocation HTTP header for your content. This tells supported browsers (currently only Mozilla Firefox) about your memory needs. This information allows the supported browser to spawn a new process using unfragmented memory space. The browser can also do extra housekeeping to make sure the large allocation succeeds. This can solve issues where the browser runs out of memory when trying to allocate the Unity heap. This is especially important on 32-bit browsers. –>

ガベージコレクションへの配慮

ガベージコレクションとは、使われていないメモリを探し出して解放するプロセスです。ガベージコレクターは、未使用のメモリを収集すると、Unity のヒープ内で再割り当てします。

For an overview on how Unity garbage collection works, see Automatic Memory Management. WebGL garbage collection runs when the stack is empty. The stack is a part of the Unity heap but not the heap itself. This usually occurs after every frame. This is different from the garbage collection process on other platforms, where the collector pauses all running threads so it can inspect the stack. This isn’t possible in JavaScript. You can debug the garbage collection process using the Unity Profiler.

On most other platforms garbage collection pauses all running threads. The garbage collector will then inspect their stacks and register for loaded object references. This isn’t currently possible in JavaScript. For this reason, the garbage collector will only run in WebGL in situations where the stack is empty. This currently happens once after every frame.

Due to this, the following code would fail running on WebGL. This is because the collector doesn’t get a chance to run the garbage collector between iterations of the loop. This means the garbage collector can’t free up memory that the intermediate string objects use, and is likely to run out of memory in the Unity heap.

string hugeString = "";
 
for (int i = 0; i < 100000; i++)
 
{
 
  hugeString += "foo";
 
}
WebGL native plug-ins for Emscripten
Cache behavior in WebGL