ASM.JS AND WEBGL FOR UNITY
Unity, the popular middleware tool isn’t limited to creating compiled applications that run as an executable.
Unity previously had a web player which was a downloadable plugin that used ActiveX. Chrome has now killed support for NPAP (Netscape Plugin API), which it announced it over one year ago. In April, with the release of Chrome 42 stable, they finally put the axe to it. There are a number of reasons as to why, but most notably they stated “hangs, crashes, security incidents, and code complexity.
Google recommends using web standards instead, such as WebGL, which I will explain below. Microsoft is also following suit and deprecating ActiveX, VBScript, attachEvent, and other legacy technologies in favor of web standards. The need for ActiveX controls has been significantly reduced by HTML5-era capabilities, which also produces interoperable code across browsers.
With the advent of WebGL and asm.js, developers can now harness much more of the power of their computing device from within the browser and provides access to markets that were previously unavailable.
HOW IS THIS CODE TURNED INTO WEBGL?
Unity recently did some performance benchmarks of their software running on WebGL as well. Having code cross-compiled (often called transpiling as well) is not without its pitfalls However, as common performance-enhancing techniques that are typically found in statically typed languages, such as multi-threading (JS is single threaded) and SIMD (Single Instruction Multiple Data) are not available in asm.js yet.
Mozilla, along with several other leading tech companies, have also been working on SIMD.js, with increased performance and reduced power usage, this could be something of the near future. Read more about it here. Instead of those performance tweaks mentioned above, Unity is relying on their new scripting runtime, IL2CPP (Intermediate Language (low-level output from .NET compilers) to C++).
That’s a story for a different post, but Unity has been doing a fantastic web series every few weeks to illustrate how IL2CPP works. IL2CPP has two distinct parts:
• An ahead-of-time (AOT) compiler
• A runtime library to support the virtual machine (VM)
The Intermediate Language (IL) from .NET compilers is compiled to C++ source code via the AOT compiler. Services and abstractions such as platform-independent access to threads and files as well as a garbage collector are some of the benefits the runtime library provides. Look at it this way:
When you run a .exe on a Windows machine, it is not actually byte code (0s and 1s) at that point. It is still in a binary that the VM reads at runtime, which is then turned into bytecode. The DotNet CLI on a Windows machine is an example of a Virtual Machine which may read this binary. The CPU cannot comprehend anything other than binary, therefore this additional step is needed to take place.
Still confused? This post explains more about the difference between machine code, byte code, and VMs.
HOW DOES ASM.JS FIT INTO THE PICTURE?
On the backend, Clang uses LLVM, which is a library for constructing, optimizing and producing intermediate and/or binary machine code (those 0s and 1s again). LLVM can be used as a compiler framework, where you provide the “front end” (parser and lexer such as Clang) and the “back end” (code that converts LLVM representation to actual machine code) Further reading: Alon Zakai of Mozilla has a fantastic slide deck which goes into further detail about how this all works.
So how cool is asm.js?
Well it has its own Twitter account, @asmjs. While the asm site is a bit sparse, it does cover the W3C spec, in addition to having a thorough FAQ. Even better, Mozilla coordinated the Humble Mozilla Bundle in 2014, which allowed you to buy a bunch of gamest that took advantage of asm.js.
WHAT IS THE WEBGL DOING?
Utilizing hardware acceleration (the GPU built into your device), WebGL is a great fit for games or complex visualizations.
Complex visual effects can be produced with small programs known as “shaders”. This may be as simple as producing a sepia coloring effect, or more complex simulations such as water or flames. Visit Shadertoy for a showcase of some examples which really highlight this.
When you build a WebGL project, Unity will create a folder with the following files:
◆ a .mem file containing a binary image to initialize the heap memory for your player.
◆ a .data file containing the asset data and scenes.
You can also customize the style of the page to better suite your game, although taking advantage of the Fullscreen API is recommended to get a more immersive experience.
Interested in learning WebGL? Look into WebGL Academy for a complete course.
WHAT’S MISSING FROM WEBGL?
WebGL is a subset of the OpenGL ES spec, this is the graphics API you frequently see on mobile devices, such as Android and iOS devices. That ES (Embedded Systems) spec is actually a subset of OpenGL, the graphics API available to desktop machines and consoles, such as Playstation and Wii. Because WebGL is not a direct 1-to-1 match with OpenGL, some features will be missing.
◆ Support for WebCam and Microphone access
◆ Hardware cursor support
◆ Most of the non-basic audio features
◆ Script debugging
◆ Any .NET features requiring dynamic code generation
WHAT ABOUT BROWSER SUPPORT?
This is where things get crazy. You can try out two of their WebGL demos right here. You need to use a browser which supports asm.js. At the time of writing (July 2015), asm.js is supported in the following browsers:
◆ Microsoft Edge (Windows 10) ◆ Mozilla Firefox
◆ Google Chrome
◆ Safari by Apple
It’s important to note that the asm.js spec is not implemented 100% in all of the browsers though, so results will vary. Unfortunately, asm.js is not listed on the popular feature- checking site CanIUse.com, so it’s difficult to get a clear understanding of how well it is supported in each browser. This will not work on mobile browsers.
WHAT ABOUT PERFORMANCE?
Here’s a short list of the missing features that are not currently available to WebGL versions of Unity games. Expect this to change over time.
◆ Runtime generation of Substance textures
◆ Networking other than WWW class (a WebSockets plug-in
◆ In almost all benchmarks, Firefox with asm.js is faster than both Chrome and Safari, and is currently the best browser to run Unity WebGL content.
◆ When you are mostly GPU-bound, you can expect WebGL to perform very similar to native code.
◆ In some areas, WebGL will actually outperform native code significantly. This is the case for tests which rely a lot on script performance (Mandelbrot and CryptoHash, which both implement their algorithms in C#), as IL2Cpp can produce more optimized code (More info in this post).
◆ Native code can still be several times faster than WebGL for areas heavily optimized to use multi-threading and/or SIMD, such as the 3D physics tests (PhysX
CASE STUDY: OWLCHEMY LABS’ AAAAA! CONVERTED TO ASM.JS FROM UNITY
One of their biggest size savers was Unity’s AudioClip streaming solution, which could stream music at runtime on demand. When completed, their final compressed WebGL build size, which includes all loaded assets as well as the Unity engine itself, ended up at 68.8 MB. The compressed standalone PC build was almost 3x that size, at 192 MB.
There were certainly some UX changes that needed to be made, including rebinding the escape key, which in many games would display a pause menu, but inside the browser would exit full screen mode and release the mouse lock. Additionally, because browser’s security model, games are forced to be sandboxed, so saving large chunks of data to disk or loading custom audio from a user’s hard drive could prove problematic.
Finally, it is important to consider a kind of cloud sync feature, as gamers often play web based games on more than one machine, it would be far more convenient for a consumer to load into their profile from any machine and have their settings / saves just appear.
Unity outlines the process of exporting your title to their WebGL player in their docs. Browser support for both WebGL and asm.js is constantly improving and Firefox even showcased features of WebGL 2.0 at the Game Developers Conference in San Francisco earlier this year. WebGL 2.0 comes with a number of improvements, including the ability to render up to 32 textures at one time, as opposed to the current standard of 8, in addition to developer access to antialiasing and multiple render targets.
The advantages of porting a Unity game to WebGL are numerous:
◆ Distribution through sources other than curated app stores ◆ Often a smaller package size
◆ Easily demo or share projects
Developers have already proven that the model works (as illustrated by the Aaaaa! Case study and the Mozilla Humble Bundle), so it’s an opportune time to take advantage of what the browser can finally offer and have additional exposure for your work.