Building WebGL Games With Unity: A Primer

Insider 24 Aug , 2020 0

What’s All The Fuss About?

This is an extension of the main piece, which you can read here. It outlines my experience with the building process of my first Unity 3D WebGL game, Last Ball.

Hopefully, you’ll be finding this before going through the process. But if you’ve already done it and have suggestions, I’d be happy to hear about them.

Before you proceed to optimize your project, install the official Build Report Inspector. It’s weird, given the importance of it, that it’s not installed by default.

Slow But Steady?!?

Last Ball is not exactly a big game. In fact, the only scene it uses, aside from the UI elements, one camera and one light, is empty – every thing is generated at run-time. Yet, the build time – warm build – takes around 10 minutes, and a cold build (that also creates shader variants), takes anywhere between 20 and 40 minutes.

Unity build report for timings.

My AMD A8-3850 CPU and 8Gb of RAM don’t do Unity any favours, but still, compared to the fact that Cocos Creator does a build in less than 3-5 minutes…

The official Unity guide states that in order to reduce IL2CPP compiling times, it helps to have a SSD (checked), add the project folder to the Windows Defender exceptions list (checked) and use incremental compiling.

Looking at the table above, less than half the time is spent compiling and more than half making the WebAssembly. In fact, during the build process, asm2wasm spikes the CPU and memory usage to over 90% 😀

I would like to know of a way to reduce the build time without investing into a super-computer, though 🙂

Build Size Is…Oversized

I was intending to slip in a “Unity momma’s so big” joke, but this is serious, god-dammit 🙂

Last Ball final build size ended up at ~14Mb. My other games, made with Cocos Creator, usually end up in the 5-7Mb range, so this is quite a difference. Factor in that Last Ball uses very few sprites/textures and very low poly models (made with ProBuilder) and 14Mb seems huge.

This is how the build report for assets look like:

Unity build report for assets and sizes.

I use the post-processing stack and the bloom effect to achive a certain look, so Unity includes the UberPost.shader. However, it also includes lots of assets that are related to post-processing effects, i.e. Thin*.png, Medium*.png and Large*.png are part of the FilmGrain filter, which I don’t use. Unity includes every effect and related assets in the post-processing stack and there is no way to automatically strip or instruct the builder to ignore effects.

It also includes assets that are related to ProBuilder: GridBox_*.png, StandardVertexColor.shader and many others. The only solution I see is to only install ProBuilder only when needed and always uninstall it before every build, but this is terribly inconvenient.

It would be nice if it were possible to instruct the Unity builder to ignore folders, but it’s not. So for this sole reason, don’t install assets that are not necessary! If you want to do so, install them in a separate project and only copy over stuff that you need.

If you install plugins (e.g. Zenject), install the bare minimum versions, not the ones containing examples/samples, or they will be included in the build!

Of course, for any other than WebGL builds, a few megabytes more is not really an issue, but for web games, it really is.

You may also notice the size of the Lit.shader as well as other shaders. Be aware of all the shader graphic options which you may find under Edit | Project Settings, Graphics section! In particular: change the “Video” to “Include if referenced”, cleanup the “Always Include Shaders” list and depending on the lighting your game uses, may want to manually alter “Lightmap modes”. In particular the later will influence the size of a shader like “Lit” (and also “Fog Modes”).

Build Size: Audio Clips

It’s also worth taking into account the import settings for the audio clips. I’m not sure why, but Unity doesn’t seem to offer MP3 as a compression format for HTML5 builds – only AAC. So you may want to consider reducing the quality to the bare minimum.

Tracker music may also present as a solution to decrease build size, but you need to find such music or musician that can compose in this format, so this is something you may need to know in advance, possibly during the pre-production of your game. Unfortunately, tracker modules doesn’t work with Unity WebGL target.

Build Size: The 80/20 Rule

It may be possible to shrink the build size further by disabling packages. For instance, Android JNI, Cloth, Physics 2D, Tilemap, Vehicles or Video, these are not something I need for Last Ball, so I’ve disabled them. Your project may be different, though.

Be aware that it’s not possible to disable all packages. For instance, disabling VR/XR or Analytics (even if you’re not using them), will result in errors. I think this may be fixed in future Unity versions, but after building the game, run it with the console open and check for any errors!

As the principle says, 80% of the effects come from 20% of the causes. Make sure that you’ve addressed the main culprits (presented in the above section), before disabling packages.

But It Worked On My Computer?

After you do the build, you may want to run it. Perhaps you have a tiny, production-oriented http server like, well, the aptly named “http-server“. You launch the server in the build folder, access the url, and the game doesn’t load. Shit.

It happens that web servers (both local and live) have to be configured to load files with unityweb or wasm extensions. So you will need a .htaccess file placed in the “Build” folder of your build (that is, My Awesome Game/Build/WebGL/Build).

For example, I’m using a simplified version (posted by one of the devs in the Unity WebGL team) which looks like this:

<IfModule mod_mime.c> 
  # The following line improves loading performance for uncompressed builds
  AddType application/wasm .wasm
 
  # Uncomment the following line to improve loading performance for gzip-compressed builds with decompression fallback
  AddEncoding gzip .unityweb
 
  # Uncomment the following line to improve loading performance for brotli-compressed builds with decompression fallback
  # AddEncoding br .unityweb
</IfModule>

I’m also using a custom build script that, after building, also copies the .htaccess file in the correct folder. If anyone is interested, I can post it.

Conclusion

To sum it up:

  • WebGL builds produced by Unity can end up being large, even if the game don’t seem to use many assets;
  • WebGL building process is slow;
  • During development, be aware to not clutter the Assets folder with stuff you don’t need;
  • Lots of assets will be included by Unity builtin packages;
  • Install the Build Report Inspector, don’t go optimizing blindly!

Written by
Stefan Dicu
Owner of Piron Games and game developer.

LEAVE A REPLY

Your email address will not be published.