Asm.js + WebGL for Unity and Unreal Engine
Unity and Epic’s Unreal Engine, the popular middleware tools frequently used by game developers, are not limited to creating compiled applications that run as an executable. With the advent of WebGL and asm.js, developers can now harness much of the power of their computing device from within the browser and access markets previously unavailable. In this tutorial, I’ll show you a slice of “how”. Unity previously had a web player, which was a downloadable plugin that used ActiveX. Chrome killed support for NPAP (Netscape Plugin API), but 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 suggests using web standards instead, such as WebGL, which I will explain below. Microsoft is 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.
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. Common performance-enhancing techniques found in statically typed languages, such as multi-threading (JS is single threaded) and SIMD (Single Instruction Multiple Data) are not available yet. Mozilla, along with several other leading tech companies, have been working on SIMD.js though, so increased performance and reduced power usage could be something of the near future. Read more about it here. Instead of those performance tweaks above, Unity is relying on their new scripting runtime, IL2CPP (In Line 2 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)
- Performance: Utilizing hardware acceleration (the GPU built into your device), WebGL is a great fit for games or complex visualizations.
- Shaders: 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.
- an index.html file that embeds your content in a web page.
- a .mem file containing a binary image to initialize the heap memory for your player.
- a .data file containing the asset data and scenes.
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. Here’s a short list of missing features 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 is available)
- 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. As of this writing (July 2015), asm.js support is as follows:
- 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).
Why would anyone want to do this?This is a pretty common question. The one I hear most though is “who would want to download a 60mb website? And you’re right — 60mb for a website is massive! But I suppose the same people who are downloading gigabytes worth of video content from YouTube and Netflix each day are those same people. If you look at it as a website, then sure, it’s huge. If you look at it as a game though, 60mb is small! The case study below illustrates that well. Furthermore, as a developer you can now circumvent the restrictions of the app store. Want to update your application? No problem, push a new build to your website. Don’t want to wait out the one-week approval process of the iOS App Store (that is, IF it gets approved)? Perfect, push to your own site. You could, of course, always sell it behind a paywall, too; or require some sort of authorization to play the title. Additionally, you do not need to pay the annual licensing fees for the app stores, nor do you need to prepare images for their stores, icons for their desktops, etc. Now things are starting to look appealing, and we’ve only just touched the surface. Take a look at what the team at Illyriad games has done with their space combat title, Age of Ascent. They initially stream only a small bit of data, just enough to get you going, before sending the additional bits to you. I believe during our last conversation it started at 50mb. You can hear more about it during the podcast I did with them. Users can hop in and play immediately. No massive client to download, and instantly lowers the barrier to entry. Teenage-me would have loved this during my Everquest years. In contrast, traditional titles send everything to you at once before you can start playing. Granted, consoles have just started to use “chunking”, which breaks up a title into smaller pieces and starts the download with the parts you need to play almost immediately. Jonas Echterhoff pointed out that in Unity, streaming assets is already possibly by using AssetBundles. Alternatively, you can try this Asset Store package, which repackages the WebGL build data, so that scenes in your build are split across multiple files, and your content can start once the first scene is loaded: https://www.assetstore.unity3d.com/en/#!/content/38368 In keeping with the space sim theme, I looked at Star Citizen, which is looking to come in at around 100gb. Do you honestly believe that you will ever experience all 100gb of that content?
An Offline ExperienceJust because you are pointing to an HTML5 site doesn’t mean you can’t have an offline experience. Don’t believe me? Take a look at this video from Syd Lawrence one of the creators of Snowbuddy. Syd runs We Make Awesome Sh and during his talk he showcases some incredible apps made with PhoneGap and his top 7 tips for making high performance PhoneGap apps at PhoneGap Day EU 2015, but specifically highlights how to create an offline experience. It would be wise to have a mix of local and remote content for your app. Technologies like IndexedDB, localStorage and AppCache, which are supported by Microsoft Edge, allow for this. A local page can be kept in your app package that can still provide a basic offline experience.
Are any other middleware tools taking advantage of this?Epic’s Unreal Engine 4 exports to WebGL and takes advantage of asm.js as well. You can find step-by-step instructions here.Their process is nearly identical to that of Unity’s minus that first C# step, as the code you write in Unreal Engine is already in C++. Epic’s current showcase piece is Tappy Chicken, a Tappy Bird type game which is also available on iOS and Android. They first illustrated UE 4 working within Firefox at GDC 2014: At GDC the year before that, Mozilla and Epic surprised everyone at one of their talks when they revealed that UDK (Unreal Engine 3) was working within the browser after only one week of work with their Epic Citadel demo. Monster Madness from NomNom Games, was the first commercial Unreal Engine 3 game published on the Web, using asm.js.
Are there other alternatives?But of course! PlayCanvas is a fantastic WebGL based framework which uses asm.js for physics. Even better, it has excellent documentation and tutorials, on top of a browser-based editor. For tools such as this, you’d need to use a wrapper of some sort (such as Cordova or PhoneGap) to port this to an app store such as Google Play, the App Store, or Windows Marketplace. ManifoldJS. ManifoldJS aims to make the life of a mobile developer easier than ever, by utilizing Web App Manifests, which allowing websites to declare app-like properties. ManifoldJS uses that standard for those platforms that support it, but falls back to Cordova for those who don’t. Cordova is great, but the W3C also considers work done at Mozilla (Firefox Open Web Apps), Google (Chrome Hosted Apps) and Microsoft has done (Windows 8 had local web apps, Windows 10 extends over to hosted web apps). With this, we can now wrap websites and creating hybrid applications which can be deployed in the various app stores, while still taking advantage of many native aspects for each device (contacts, calendar, file storage, gyro, GPS, etc.) Jeff Burtoft explains hosted web apps very well at http://www.thishereweb.com/hosted-web-apps-explained/ When we combine the two, we can create applications at native speed which can be deployed in a number of app stores, and utilizing largely one code base. There is no silver bullet for mobile development, but this certain makes the process easier.
ConclusionUnity 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 was even showcasing 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
- Scan your site for out-of-date libraries, layout issues, and accessibility
- Use virtual machines for Mac, Linux, and Windows
- Remotely test for Microsoft Edge on your own device
- Coding Lab on GitHub: Cross-browser testing and best practices
- Woah, I can test Edge & IE on a Mac & Linux! (from Rey Bango)
- The Edge Rendering Engine that makes the Web just work (from Jacob Rossi)
- Unleash 3D rendering with WebGL (from David Catuhe including the vorlon.JS and babylonJS projects)
- Hosted web apps and web platform innovations (from Kevin Hill and Kiril Seksenov including the manifold.JS project)