Unity 5 and WebGL porting guide

July 19, 2016
protect

So, you have been working on Mobile games for a while using Unity, and probably heard that with Unity 5 it was possible to port your games for the Web sans Unity Web Player.

Great, right? Well, yeah, but there are a few things to know before making your game work with WebGL.

Let's start by answering the following question:

Why is WebGL so important for game development?

For starters the Web has always been a strong platform with an established user base of about everyone. At the time of writing this, with WebGL you can target almost every desktop platform that has a relatively modern Web browser without the need of installing any additional plugins.

But the most important part of building for the Web is that you control the distribution. Forget about sending your build for review, or uploading your package through a console and waiting hours to test your build. With web technologies it has always been a matter of uploading your files via FTP and seeing the changes reflected in real time.

This is clearly and advantage when you are iterating fast and want to test your latest build on an environment that resembles production.

Also important to mention is that Google Chrome has recently dropped support for NPAPI, which means plugin based games (like those using Unity Web Player) won't longer run on that Browser. Other browsers may follow in this decision in the future, so it's better to be prepared.

But enough for an introduction, let's move  on to the interesting stuff. As with any other platform, when you build your Unity 5 project for WebGL, there are a few things to take into consideration.

 

Here's a handy list of issues we ran into when porting our first game from Android/iOS to Facebook Canvas (all this information can also be found on Facebook's Developer Documentation and/or Unity docs):

First things first: Unsupported Namespaces

  • Everything in the System.Net namespace (particularly System.Net.Sockets) are non-functional in WebGL.

According to Unity docs, this is because:

Due to security implications, JavaScript code does not have direct access to IP Sockets to implement network connectivity.

If you need to use Networking in WebGL, you currently have the options to use the WWW or UnityWebRequest classes in Unity or the new Unity Networking features. It'll bring some headaches because of CORS (Cross-origin resource sharing), which basically means you won't be able to access any other URL that is not in the same domain as the one where your game is hosted. Alternatively, you can also shoot yourself in the foot... mhhh, I mean, if you own the server that you are trying to access, you can add some headers to your Apache configuration to enable CORS.

This is probably one of the biggest headaches you'll have to solve in order to port your game to WebGL (if you use asset bundles or need to download resources from an external server).

  • Just in case you were wondering:

The same applies to Unity’s old UnityEngine.Network* classes, which are not available when building for WebGL.

Let's make it clear: this is not Unity's fault, at all, it's just the way the Web is designed to work.

  • WebGL is an AOT (ahead of time) platform, so it does not allow dynamic generation of code using System.Reflection.Emit.

  • Basically, anything in the System.Threading namespace is not supported.

So far we've dealt with unsupported namespaces. For us, the way to work around these issues was to use Visual Studio 2015's search tools to do a search in our Entire Solution for files where those namespaces were being imported (using namespace blabla). Afterwards we would add a pre-processor directive for !UNITY_WEBGL, and find a way to fix all the errors that came up when the offending namespaces where removed (with further uses if UNITY_WEBGL).

Example:

#if !UNITY_WEBGL
using System.Threading;
#endif

Second: Asset bundles

There are some considerations when using AssetBundles on the WebGL platform:

  • When you are using class types in your AssetBundle which are not used in your main build, this can cause Unity to strip the code for those classes from the build, which will then cause it to fail when trying to load assets from the AssetBundle. Information about how to deal with this issue can be found here.

  • Since WebGL does not support threading, and since http downloads will only become available when finished, Unity WebGL builds need to decompress AssetBundle data on the main thread when the download is done, thus blocking the main thread. To avoid this interruption, you may want to avoid using the default LZMA Format for your AssetBundles, and compress using LZ4 instead, which is decompressed very efficiently on-demand. If you need smaller compression sizes then LZ4 delivers, you can configure your web server to gzip-compress the files on the http protocol level (on top of LZ4 compression).

Third: Building and Testing

This is probably one of the worse parts of building for WebGL. It's not clear what each setting does to the final build or how you are supposed to test and debug your game. Read through this section to find out and thank me later.

  • You can view your WebGL player directly in most browsers by simply opening the index.html file. For security reasons, Chrome places restrictions on scripts opened from local file:// URLs, so this technique will not work. If you use Unity’s Build & Run command (menu: File > Build & Run) then the file will be temporarily hosted in a local web server and opened from a localhost URL (this avoids the security restrictions). You can also run Chrome with the --disable-web-security command line option to enable it to load content from file: urls.

In our case, we created a simple *.bat script with this single line (edit accordingly if you installed Chrome in another directory):

"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security

At least in Windows, you'll be able to have the script in your desktop and double-click it to launch a Chrome window that will allow CORS. We found this is the simplest way to test builds on the fly and used this flow during our process. It even works for builds that are hosted on a server.

  • Tips for building:

These are quoted word to word from Unity docs, but we marked those that we've found have the most effect in the final build size and performance.

JikGuard.com, a high-tech security service provider focusing on game protection and anti-cheat, is committed to helping game companies solve the problem of cheats and hacks, and providing deeply integrated encryption protection solutions for games.

Read More>>