📜 ⬆️ ⬇️

WebGL: transfer game from mobile platform to desktop

Creating a desktop version of the mobile game has become a real research mission for the Krasnodar studio Plarium. In this article, we will describe how we switched to the WebGL technology when moving the Vikings: War of Clans project to a new platform.

image

Mastering WebGL


The game Vikings: War of Clans was created on the cross-platform engine Unity 3D, which allows you to run the application on more than 25 platforms: from a mobile device to the browser. We already had experience with Adobe Flash, but for this project we chose WebGL technology, and here's why:


It is worth noting that the developers of Unity provide high-quality technical support and extensive documentation. When working on the project, we received all the necessary information about the limitations for WebGL in the user manual and in the forums dedicated to this engine, so that you will not be left without help.
')

Translation difficulties


In order to build a WebGL build, the Unity engine performs a complex chain of actions: using Mono C # compiler, the game code is converted into intermediate (IL) code, and then using IL2CPP technology, the code in C ++ is obtained, which in turn gives us the WebGL project through the Emscripten compiler. As a result, not all .Net features provided by the Unity 3D engine are available in the final assembly. For example, multithreading is not supported, System.Net.Sockets does not work, etc.

To complete the transition to the web version, we had to fix a number of problems.

WebSockets implementation . For networking, a wrapper was written that, with minimal changes, allowed us to work with the server through web sockets. A simple example is available in the Unity Asset Store .

Lack of multithreading . If in the mobile version, different processes were launched in parallel in separate threads and were not interrupted until they were completely completed, then the single-threading characteristic of the web version required a different approach in order to prevent application hangs. To do this, we transferred all actions to coroutine and thus achieved the distribution of the load over time.

Opening tabs . Unity transfers the recorded user actions to the buffer and transfers them during the internal frame update. In such a situation, the browser protection does not allow to open another window. The problem was solved by a small extension to the engine - a native browser plug-in, into which mouse events are directly thrown.

OpenURL: function(url){ window.open(Pointer_stringify(url)); } 

So managed to achieve the opening of all the necessary windows. About creating plugins for WebGL is written in the official documentation and in the blog of developers .

Fonts . At some point, there was a need to refine the display of characters. In particular, the input of hieroglyphs should be done as follows: the user types in combinations of Latin letters, which are converted into Japanese, Chinese or Korean letters. In Unity itself, this method is not provided, but this functionality is in browsers. We implemented it using a separate plug-in. In addition, WebGL, unlike native applications of the same Flash, does not have access to system fonts. Therefore, we added them directly to the project, which, of course, increased the size of the assembly.

Texture quality settings . It took a lot of time to adjust the balance between the quality of texture compression and the size of the build. It was necessary to experimentally find out which textures are transferred from the mobile version, you can pinch, and which not. Gradually, we came to the optimal settings, which are now automatically set.

In our game there are several atlases for textures, and, as a rule, we use DXT1- and DXT5-compression (depending on the presence or absence of an alpha channel in them). The exceptions are two atlases: containing textures that are extremely bad at compressing (textures with a gradient, buttons with numbers or letters) and a satin for emoji symbols. In these cases, we use RGBA32.

To reduce the size of all other textures that are outside the atlases, the formats DXT1Crunched and DXT5Crunched are suitable. At the moment, we have redefined the OnPreprocessTexture method of AssetPostprocessor, which allowed us to automatically apply these settings to all textures in the project.

Third-party services . Be prepared for the fact that third-party libraries that are effectively used in a mobile game may not work correctly or even not work at all when building a WebGL project. In such a situation, the best way out is to find an alternative. For example, for authorization on Facebook, we additionally used the native JavaScript plugin. It allows you to identify the user already at the time of loading the page and obtain in advance the permissions (permissions) required for the game.

Moving from Unity 5.2 to 5.6 . During the development process, we needed to switch from Unity 5.2 to version 5.6, in which Unity Loader was added and several critical issues were fixed (for example, a build crash during a page reload). These changes greatly simplified the initialization of the application. You can see the download code for the builds of both versions below.

Unity 5.2:

 var canvas = document.createElement("canvas"); canvas.style.width = "100%"; canvas.style.height = "100%"; canvas.addEventListener("contextmenu", function(e) { e.preventDefault() }), canvas.id = "canvas"; gameContainer.appendChild(canvas); if (consts.isDebug) { createScript('unity52/module_pre_debug.js?v=' + consts.appVersion); document.WebExistsGLCallback = function() { Module.postRun.push(unityHelper.postRun); createScript('Debug/Release/fileloader.js?v=' + consts.appVersion); createScript('unity52/module_post_debug.js?v=' + consts.appVersion); tracker.load(); }; createScript('unity52/UnityConfig.js?v=' + consts.appVersion); } else { createScript('unity52/module_pre.js?v=' + consts.appVersion); document.WebExistsGLCallback = function() { Module.postRun.push(unityHelper.postRun); createScript('Release/fileloader.js?v=' + consts.appVersion); createScript('unity52/module_post.js?v=' + consts.appVersion); tracker.load(); }; createScript('unity52/UnityConfig.js?v=' + consts.appVersion); } 

Unity 5.6:

 unityHelper.url = consts.isDebug ? "Debug/Build/Debug.json" : "Build/WebGL.json"; Module = UnityLoader.instantiate(gameContainer, unityHelper.url, { onProgress: function(a, b) { preloader.setProgress(b); }, Module: { resolveBuildUrl: function(buildUrl) { return (buildUrl.match("/(http|https|ftp|file):\/\//") ? buildUrl :unityHelper.url.substring(0, unityHelper.url.lastIndexOf("/") + 1) + buildUrl) + "?v=" + consts.appVersion; }, postRun: [unityHelper.postRun], }, }).Module; 

New experience for new projects


On the implementation of the desktop version of Vikings: War of Clans took six months. Most of the time, we created a new UI and spent about two months doing technical work to migrate to WebGL.

Taken as Throne: Kingdom at War, we already knew what was to be done and in what time frame we could meet. Due to this, the second project moved to the web platform faster - in just 4 months. Note that in both cases, mobile games expanded their functionality, while their desktop versions were approaching the exit to production, so individual elements of the UI were adjusted already in the process.

image

Developer Tips



We hope that the experience of the studio Plarium-South will open up new opportunities for your projects.

Source: https://habr.com/ru/post/343084/


All Articles