- PVSM.RU - https://www.pvsm.ru -
Создание десктопной версии мобильной игры стало настоящей исследовательской миссией для краснодарской студии Plarium. В этой статье мы расскажем, как перешли на технологию WebGL при переносе проекта Vikings: War of Clans на новую платформу.

Игра Vikings: War of Clans создавалась на кроссплатформенном движке Unity 3D, который позволяет запускать приложение более чем на 25 платформах: от мобильного устройства до браузера. У нас уже был опыт работы с Adobe Flash, но для этого проекта мы выбрали технологию WebGL, и вот почему:
Стоит отметить, что разработчики Unity предоставляют качественную техническую поддержку и развернутую документацию. При работе над проектом мы получали всю необходимую информацию об ограничениях для WebGL в руководстве пользователя и на форумах, посвященных этому движку, так что без помощи вы точно не останетесь.
Для того чтобы собрать WebGL-билд, движок Unity проделывает сложную цепочку действий: используя Mono C# compiler, код игры преобразуется в промежуточный (IL) код, а затем с помощью технологии IL2CPP получается код на языке C++, который в свою очередь отдает нужный нам WebGL-проект через компилятор Emscripten. В результате не все возможности .Net, предоставляемые движком Unity 3D, доступны в окончательной сборке. Например, не поддерживается многопоточность, не работает System.Net.Sockets и т. д.
Для полноценного перехода к веб-версии нам предстояло устранить ряд проблем.
Реализация WebSockets. Для сетевого взаимодействия была написана обертка, которая с минимальными изменениями позволила нам работать с сервером через веб-сокеты. Простой пример доступен в Unity Asset Store [1].
Отсутствие многопоточности. Если в мобильной версии различные процессы запускались параллельно в отдельных потоках и не прерывались до полного завершения, то характерная для веб-версии однопоточность требовала другого подхода, чтобы не допустить подвисаний приложения. Для этого мы перевели все действия на coroutine и таким образом добились распределения нагрузки по времени.
Открытие вкладок. Unity перемещает записанные действия пользователя в буфер и передает их во время внутреннего апдейта фрейма. В такой ситуации защита браузеров не позволяет открыть еще одно окно. Проблему решило небольшое расширение к движку — нативный плагин к браузеру, в который напрямую прокидываются события мыши.
OpenURL: function(url){
window.open(Pointer_stringify(url));
}
Так удалось добиться открытия всех необходимых окон. О создании плагинов под WebGL написано в официальной документации [2] и в блоге разработчиков [3].
Шрифты. В определенный момент возникла потребность доработать отображение символов. В частности, ввод иероглифов должен осуществляться так: пользователь набирает комбинации латинских букв, которые преобразуются в японские, китайские или корейские письменные знаки. В самом Unity этот способ не предусмотрен, зато такой функционал есть в браузерах. Мы реализовали его с помощью отдельного плагина. Кроме того, WebGL, в отличие от нативных приложений и того же Flash, не имеет доступа к системным шрифтам. Поэтому мы добавляли их непосредственно в проект, что, конечно, увеличивало размер сборки.
Настройки качества текстур. Немало времени ушло на то, чтобы настроить баланс между качеством сжатия текстур и размером билда. Предстояло опытным путем выяснить, какие текстуры, переносимые из мобильной версии, можно пережимать, а какие нет. Постепенно мы пришли к оптимальным настройкам, которые теперь выставляются автоматически.
В нашей игре существуют несколько атласов для текстур, и, как правило, мы используем DXT1- и DXT5-компрессии (в зависимости от наличия или отсутствия в них альфа-канала). Исключением являются два атласа: содержащий текстуры, которые крайне плохо реагируют на сжатие (текстуры с градиентом, кнопки с цифрами или буквами) и атлас для emoji-символов. В этих случаях мы используем RGBA32.
Для уменьшения размеров всех остальных текстур, находящихся вне атласов, подходят форматы DXT1Crunched и DXT5Crunched. На данный момент мы переопределили метод OnPreprocessTexture у AssetPostprocessor, что позволило в автоматическом режиме применить эти настройки для всех текстур в проекте.
Сторонние сервисы. Будьте готовы к тому, что сторонние библиотеки, которые эффективно используются в мобильной игре, могут некорректно работать или даже не работать вовсе при сборке WebGL-проекта. В такой ситуации лучший выход — найти альтернативу. Например, для авторизации на Facebook мы дополнительно применяли нативный плагин JavaScript. Он позволяет идентифицировать пользователя уже во время загрузки страницы и заранее получить разрешения (permissions), требуемые для игры.
Переход от Unity 5.2 к 5.6. В процессе разработки у нас возникла необходимость перехода от версии Unity 5.2 к версии 5.6, в которой добавился Unity Loader и было исправлено несколько критических проблем (например, падение билда по памяти при перезагрузке страницы). Эти изменения существенно упростили инициализацию приложения. Вы можете ознакомиться с кодом загрузки билдов обеих версий ниже.
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;
На реализацию десктопной версии Vikings: War of Clans ушло полгода. Большую часть времени мы создавали новый UI и около двух месяцев проводили технические работы для перехода на WebGL.
Принимаясь за Throne: Kingdom at War, мы уже понимали, что предстоит сделать и в какие сроки сможем уложиться. Благодаря этому второй проект перешел на веб-платформу быстрее — всего за 4 месяца. Отметим, что в обоих случаях мобильные игры расширяли свой функционал, пока их десктопные версии приближались к выходу в продакшн, поэтому отдельные элементы UI корректировались уже в процессе работы.

Мы надеемся, что опыт студии Plarium-South откроет новые возможности для ваших проектов.
Автор: Plarium
Источник [4]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/webgl/269043
Ссылки в тексте:
[1] Unity Asset Store: https://www.assetstore.unity3d.com/en/?&_ga=2.38304355.1753005909.1510002027-134523977.1481042991#!/content/38367e
[2] официальной документации: https://docs.unity3d.com/Manual/webgl-interactingwithbrowserscripting.html
[3] блоге разработчиков: https://blogs.unity3d.com/ru/2015/05/06/an-introduction-to-ilcpp-internals/
[4] Источник: https://habrahabr.ru/post/343084/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.