Version: 2021.1
WebGL Networking
Using WebGL templates

Building and running a WebGL project

The Build folder contains the following files ([ExampleBuild] represents the name of the target build folder):

File name Contains
[ExampleBuild].loader.js The JavaScript code that the web page needs in order to load the Unity content.
[ExampleBuild].framework.js JavaScript runtime and plugins.
[ExampleBuild].wasm WebAssembly binary.
[ExampleBuild].mem A binary image to initialize the heap memory for your Player. Unity only generates this file for multi-threaded WebAssembly builds.
[ExampleBuild].data Asset data and ScenesA Scene contains the environments and menus of your game. Think of each unique Scene file as a unique level. In each Scene, you place your environments, obstacles, and decorations, essentially designing and building your game in pieces. More info
See in Glossary
.
[ExampleBuild].symbols.json Debug symbol names necessary to demangle an error stack trace. This file is only generated for Release builds when you enable the Debug Symbols option (File > Build Settings > Player Settings.)
[ExampleBuild].jpg A background image, which displays while the build is loading. This file is only generated when a Background Image is provided in the Player Settings (File > Build Settings > Player Settings > Splash Image). See the Splash Screen page for further information.

If you enable a CompressionA method of storing data that reduces the amount of storage space it requires. See Texture Compression, Animation Compression, Audio Compression, Build Compression.
See in Glossary
Method
for your build, Unity identifies the extension that corresponds with the compression method and adds this extension to the names of the files inside the Build subfolder. If you enable Decompression Fallback, Unity appends the extension .unityweb to the build file names. Otherwise, Unity appends the extension .gz for the Gzip compression method, or .br for the Brotli compression method. For more information, see WebGL: Compressed builds and server configuration.

If you enable Name Files As Hashes (in the Player Settings), Unity uses the hash of the file content instead of the default filename. This applies to each file in the build folder. This option allows you to upload updated versions of the game builds into the same folder on the server, and only upload the files which have changed between build iterations.

The best way to view the WebGL Player locally is to use Unity’s Build And Run option (menu: File > Build And Run). Unity uses a local web server to host your build, and opens it from a localhost URL. Alternatively, you can use a custom local web server with properly configured response headers. For more information on setting up response headers, see WebGL: Compressed builds and server configuration.

Note: Opening a Player directly from the file system might not work in some browsers. This is due to security restrictions applied to local file URLs.

Build Settings

To access the WebGL build settings, open the Build Settings window (File > Build Settings). Then select WebGLA JavaScript API that renders 2D and 3D graphics in a web browser. The Unity WebGL build option allows Unity to publish content as JavaScript programs which use HTML5 technologies and the WebGL rendering API to run Unity content in a web browser. More info
See in Glossary
from the Platform list.

Build Settings Window
Build Settings Window

Development Build

When you select the Development BuildA development build includes debug symbols and enables the Profiler. More info
See in Glossary
setting, Unity generates a development build which has Profiler support and a development console which you can use to see any errors in your application. Additionally, development builds do not minify content. The JavaScript in development builds are in human-readable form, and Unity preserves function names so you can see stack traces for errors. However, this means development builds are very large, and too large to distribute. You can only select Autoconnect Profiler and Deep Profiling Support if you enable the Development Build setting.

Autoconnect Profiler

Enable the Autoconnect Profiler setting to profile your Unity WebGL content. For WebGL, it is not possible to connect the ProfilerA window that helps you to optimize your game. It shows how much time is spent in the various areas of your game. For example, it can report the percentage of time spent rendering, animating, or in your game logic. More info
See in Glossary
to a running build as on other platforms, so you have to use this option to connect the content to the Editor. This is because the Profiler connection is handled using WebSockets on WebGL, but a web browser only allows outgoing connections from the content.

Deep Profiling Support

Enable the Deep Profiling Support setting to make the Unity Profiler profile every function call in your application. For more information see the documentation on Deep Profiling.

Player settings

WebGL has some additional options in the Player settingsSettings that let you set various player-specific options for the final game built by Unity. More info
See in Glossary
(menu: Edit > Project SettingsA broad collection of settings which allow you to configure how Physics, Audio, Networking, Graphics, Input and many other areas of your project behave. More info
See in Glossary
, then select the Player category).

Other Settings

Strip Engine Code

Open Other Settings to access the Strip Engine Code option. This option is checked by default to enable code stripping for WebGL. With this option checked, Unity does not include code for any classes you don’t use. For example, if you don’t use any physics components or functions, the whole physics engineA system that simulates aspects of physical systems so that objects can accelerate correctly and be affected by collisions, gravity and other forces. More info
See in Glossary
is removed from your build. See the Stripping section below for more details.

Publishing Settings

Enable Exceptions

Open Publishing Settings to access Enable Exceptions. Enable Exceptions allows you to specify how unexpected code behavior (generally considered errors) is handled at run time. It has these options:

  • None: Select this if you don’t need any exception support. This gives the best performance and smallest builds. With this option, any exception thrown causes your content to stop with an error in that setting.
  • Explicitly Thrown Exceptions Only (default): Select this to capture exceptions which are explicitly specified from a throw statement in your scriptsA piece of code that allows you to create your own Components, trigger game events, modify Component properties over time and respond to user input in any way you like. More info
    See in Glossary
    and to also ensure finally blocks are called. Note that selecting this option makes the generated JavaScript code from your scripts longer and slower; This might only be an issue if scripts are the main bottleneck in your project.
  • Full Without Stacktrace: Select this option to capture:
    • Exceptions which are explicitly specified from throw statements in your scripts (the same as in the Explicitly Thrown Exceptions Only option)
    • Null References
    • Out of Bounds Array accesses
  • Full With Stacktrace: This option is similar to the option above but it also captures Stack traces. Unity generates these exceptions by embedding checks for them in the code, so this option decreases performance and increases browser memory usage. Only use this for debugging, and always test in a 64-bit browser.

Select Publishing Settings to access Data Caching.

Data Caching

To access Data Caching, select Publishing Settings (File > Build Settings > Player Settings > WebGL > Publishing Settings). This enables the browser to cache the main data files into the IndexedDB database.

Using the default browser HTTP cache does not guarantee that the browser caches a particular response. This is because the browser HTTP cache has limited space, and the browser might not be able to cache files that are too large.

To improve your loading speed, IndexedDB allows you to cache files above the browser limit. When you cache more files, you increase the chance that downloaded content is available on the user’s machine during the next run of the build.

Data Caching only caches the .data files in the IndexedDB cache for HTTP responses. To cache AssetBundles, you need to enable Data Caching and override unityInstance.Module.cacheControl(). To do this, make sure Module.cacheControl(url) returns must-revalidate for the requested AssetBundle URL. For example, you can override the unityInstance.Module.cacheControl() function in the fulfillment callback of the Promise that createUnityInstance() returns. For further information on createUnityInstance() see WebGL: Compressed builds and server configuration.

When publishing for WebGL, it is important to keep your build size low so users get reasonable download times before the content starts. For generic tips on reducing asset sizes, see documentation on Reducing the file size of the build.

Distribution size

When publishing for WebGL, it is important to keep your build size low so users get reasonable download times before the content starts. For generic tips on reducing asset sizes, see documentation on Reducing the file size of the build.

Hints and tips specific to WebGL

  • Specify the Crunch texture compression3D Graphics hardware requires Textures to be compressed in specialized formats which are optimized for fast Texture sampling. More info
    See in Glossary
    format for all your compressed textures in the Texture Importer.

  • Don’t deploy development builds; they are not compressed or minified, and so have much larger file sizes.

  • Open the Player settings (menu: Edit > Project Settings, then select the Player category), open the Publishing Settings panel and set Enable Exceptions to None if you don’t need exceptions in your build.

  • Open the Player settings (menu: Edit > Project Settings, then select the Player category), open the Other Settings panel, and enable Strip Engine Code to ensure an efficient build.

  • Take care when using third-party managed dlls, as they might include a lot of dependenciesIn the context of the Package Manager, a dependency is a specific package version (expressed in the form package_name@package_version) that a project or another package requires in order to work. Projects and packages use the dependencies attribute in their manifests to define the set of packages they require. For projects, these are considered direct dependencies; for packages, these are indirect, or transitive, dependencies. More info
    See in Glossary
    and so significantly increase the generated code size.

If you make a release build, Unity compresses the build output files according to the Compression Format selected in the Publishing Settings panel of the WebGL Player settings.

See documentation on Deploying compressed builds for more info on these options, and on how to publish builds with them.

AssetBundles

Since all your Asset data needs to be pre-downloaded before your content starts, you should consider moving Assets out of your main data files and into AssetBundles. That way, you can create a small loader Scene for your content which loads quickly. It then dynamically loads Assets on-demand as the user proceeds through your content. AssetBundles also help with Asset data memory management: You can unload Asset data from memory for Assets you don’t need any more by calling AssetBundle.Unload.

Some considerations apply when using AssetBundles on the WebGL platform:

  • When you use class types in your AssetBundle which are not used in your main build, Unity may strip the code for those classes from the build. This can cause a fail when trying to load Assets from the AssetBundle. Use BuildPlayerOptions.assetBundleManifestPath to fix that, or see the section on Stripping, below, for other options.

  • WebGL does not support threading, but http downloads only become available when they have finished downloading. Because of this, Unity WebGL builds need to decompress AssetBundle data on the main thread when the download is done, blocking the main thread. To avoid this interruption, LZMA AssetBundle compression is not available for AssetBundles on WebGL. AssetBundles are compressed using LZ4 instead, which is de-compressed very efficiently on-demand. If you need smaller compression sizes than LZ4 delivers, you can configure your web server to use gzip or Brotli compression (on top of LZ4 compression) on your AssetBundles. See documentation on Deploying compressed builds for more information on how to do this.

  • WebGL supports AssetBundle caching with UnityWebRequestAssetBundle.GetAssetBundle. This method uses the IndexedDB API from your browser to store a cache on the user’s device. Some browsers might have limited support for IndexedDB and any browsers might request the user’s authorization to store data on the disk. For more information, see WebGL browser compatibility.

Stripping

Unity removes all unused code from your build by default. You can change this via the Player settings (menu: Edit > Project Settings, then select the Player category): Select the Other Settings panel to access the Strip Engine Code option. It is better to build with stripping enabled.

With code stripping, Unity scans your project for any UnityObject-derived classes used (either by being referenced in your script code, or in the serialized data in your Scenes). It then removes from the build any Unity subsystems which have none of their classes used. This makes your build have less code, resulting in both smaller downloads and less code to parse (so code runs faster and uses less memory).

Issues with code stripping

Code stripping might cause issues with your project if it strips code which is actually necessary. This can be the case when you load AssetBundles at run time which contain classes that are not included in the main build, and have therefore been stripped from the project. Error messages appear in your browser’s JavaScript console when this happens (possibly followed by more errors). For example:

Could not produce class with ID XXX

To troubleshoot these errors, look up the ID (such as XXX in the example above) in the Class ID Reference to see which class it is trying to create an instance of. In such cases, you can force Unity to include the code for that class in the build, either by adding a reference to that class to your scripts or to your Scenes, or by adding a link.xml file to your project.

Below is an example which makes sure that the ColliderAn invisible shape that is used to handle physical collisions for an object. A collider doesn’t need to be exactly the same shape as the object’s mesh - a rough approximation is often more efficient and indistinguishable in gameplay. More info
See in Glossary
class (and therefore the Physics module) gets preserved in a project. Add this XML code to a file called link.xml, and put that file into your Assets folder.

<linker>
    <assembly fullname="UnityEngine">
        <type fullname="UnityEngine.Collider" preserve="all"/>
    </assembly>
</linker>

If you suspect that stripping is causing problems with your build, you can also try disabling the Strip Engine Code option during testing.

Unity does not provide a convenient way to see which modules and classes are included in a build, which would allow you to optimize your project to strip well. However, to get an overview of included classes and modules, you can look at the generated file Temp/StagingArea/Data/il2cppOutput/UnityClassRegistration.cpp after making a build.

Note that the Strip Engine Code option only affects Unity engine code. IL2CPPA Unity-developed scripting back-end which you can use as an alternative to Mono when building projects for some platforms. More info
See in Glossary
always strips byte code from your managed dlls and scripts. This can cause problems when you need to reference managed types dynamically through reflection rather than through static references in your code. If you need to access types through reflection, you may also need to set up a link.xml file to preserve those types. See the documentation page on iOS Build size optimization for more information on link.xml files.

Moving build output files

To change the location of your Build folder, modify the buildUrl variable in the WebGL Template index.html file.

To change the location of the files inside the Build folder, change their URLs (that is, dataUrl, wasmCodeUrl, wasmMemoryUrl, and wasmFrameworkUrl) in the parameters to the config variable in the index.html file.

You can specify URLs on external servers for these if you want to host your files on a content distribution network (CDN), but you need to make sure that the hosting server has enabled Cross Origin Resource Sharing (CORS) for this to work. See the manual page on WebGL networking for more information about CORS.

Incremental builds

The C++ code generated for your project by IL2CPP is compiled incrementally; that is, only generated C++ code that has changed since the last build is compiled again. Unchanged source code re-uses the same object files generated for the previous build. The object files used for incremental C++ builds are stored in the Library/il2cpp_cache directory in your Unity project.

To perform a clean, from-scratch build of the generated C++ code which doesn’t use incremental compiling, delete the Library/il2cpp_cache directory in your Unity project. Note that if the Unity Editor version differs from the one used for the previous WebGL build, Unity does a clean, from-scratch build automatically.


  • Full Without Stacktrace added in Unity 2017.3
  • Removed asm.js linker target in Unity 2019.1
  • Build file updates and Data Caching added in Unity 2020.1
WebGL Networking
Using WebGL templates