Розробка ігор на WebGL
Клієнт хочет гру, яка запускається по посиланню — без встановлення, без app-store, прямо в браузері. Звучить просто. На ділі WebGL-гра живе в крайньо обмеженому середовищі: один потік, обмежена пам'ять, sandbox без доступу до файлової системи, та Safari, який реалізує WebGL інакше, ніж Chrome.
Чим WebGL відрізняється від нативного білду
Пам'ять — головне обмеження
Unity WebGL компілює C# у WebAssembly через IL2CPP та запускає все в одному браузерному потоці. Браузер виділяє лінійну пам'ять (Heap) при старті — за замовчуванням 256 МБ. Перевищення цього ліміту приводить до Out of Memory та краху сторінки.
На практиці це означає:
- Усі ассети, завантажені через Resources.Load або Addressables, живуть в одному пулі пам'яті разом з wasm-кодом та стеком.
- Текстури потрібно жати агресивно: ETC2 та ASTC не підтримуються WebGL — тільки DXT (Desktop) та PVRTC (Safari/iOS, з застереженнями). Використовуємо crunch compression + fallback на несжаті для Safari.
- AudioClip у форматі WAV — 40 МБ. Той же кліп у Vorbis (OGG) — 3 МБ. У контексті 256 МБ heap це критично.
Для проектів з великим обсягом контенту переходимо на ліміт у 512 МБ через PlayerSettings.WebGL.memorySize, але пам'ятаємо: це зарезервовується одразу при завантаженні сторінки, незалежно від фактичного використання.
Відсутність багатопоточності та workarounds
WebAssembly threading потребує SharedArrayBuffer, який заблокований на більшості хостингів без правильних CORS-заголовків (Cross-Origin-Opener-Policy: same-origin + Cross-Origin-Embedder-Policy: require-corp). На практиці в 2024-2025 році threading включаємо тільки якщо контролюємо сервер.
Без threading усі задачі — фізика, анімації, аудіо-декодування — виконуються в головному потоці. Це обмеження змушує інакше думати про архітектуру:
- Coroutines з yield замість важких Update() циклів — дозволяє розмазати обчислення по кадрам.
- Burst Compiler у WebGL працює навіть без threading — компілює гарячі шляхи в SIMD-оптимізований wasm.
- Алгоритми з O(n²) складністю, які непомітні на ПК, вбивають framerate у браузері.
Розмір білду та час завантаження
Стандартний Unity WebGL білд без оптимізації важить 30-60 МБ (gzip). Користувач чекає завантаження — і йде. Оптимізуємо:
-
Code Stripping —
Managed Stripping Level: High. Видаляє невикористаний .NET код. Економить 5-15 МБ. - IL2CPP Code Generation: Faster runtime для продакшена (повільніша компіляція, швидший runtime).
-
Brotli compression замість gzip — сервер повинен підтримувати
Content-Encoding: br. Стиск кращий на 15-20%. - Addressables для ассетів — завантажуємо тільки те, що потрібно для поточної сцени, решту за вимогою.
Реальний кейс: гіпер-казуальна гра для маркетингової кампанії. Початковий білд — 48 МБ gzip. Після stripping, оптимізації текстур та розбивки на Addressable-бандли — 11 МБ початкова завантаження, решта ассетів підгружалася в фоні. Час до першого геймплею скоротився з 18 до 4 секунд.
Стек та інструменти
Рушій: Unity 2022 LTS / 2023.x, URP (Built-in pipeline для WebGL небажаний — legacy). ShaderGraph з обмеженнями: деякі ноди не транслюються в WebGL GLSL коректно, перевіряємо через Preview в редакторі.
Взаємодія з браузером: JavaScript-плагіни через jslib файли в Assets/Plugins/WebGL/. Виклик JS з C# через [DllImport("__Internal")]. Виклик C# з JS через SendMessage() або Module.dynCall. Для складних інтеграцій (OAuth, платіжні системи, аналітика) — власна JS-обертка поверх Unity.
Мультиплеєр у WebGL: WebSocket замість UDP. Mirror з Transport SimpleWebTransport — працює через WSS (WebSocket Secure). Photon Fusion підтримує WebGL через WebSocket relay. Latency вищий, ніж UDP, — закладаємо в дизайн.
Аналітика та реклама: UnityAds для WebGL працює через iframe. Для власної аналітики — прямі виклики через jslib до Google Analytics / Amplitude. Firebase SDK у WebGL — тільки Firebase Analytics та Firestore (Auth та Realtime Database — обмежено).
Сумісність браузерів
| Браузер | WebGL 2.0 | Threading | Примітки |
|---|---|---|---|
| Chrome 100+ | Так | Так (з COOP/COEP) | Найкраща підтримка |
| Firefox 100+ | Так | Так (з COOP/COEP) | Хороша підтримка |
| Safari 15+ | Так | Нї | Особливості роботи з пам'яттю |
| Edge (Chromium) | Так | Так (з COOP/COEP) | Аналогічно Chrome |
| Mobile Chrome | Так | Нї | GPU throttling у фоні |
| Mobile Safari | Частково | Нї | Багато обмежень |
Тестуємо на реальних пристроях. BrowserStack або LambdaTest — для автоматизації.
Процес розробки
Аналіз вимог (2-3 дні). Визначаємо: цільові браузери, вимоги до пам'яті, потрібна лі мультиплей, інтеграція з зовнішніми сервісами (авторизація, платежі, аналітика). WebGL-проект починається з обмежень, а не з фіч.
Архітектура ассетів. Планюємо Addressable Groups на старті — які ассети в початковому білді, що підгружається по ходу. Помилка — додавати Addressables в середині проекту: це рефакторинг всіх шляхів завантаження.
Розробка та оптимізація. Паралельно з розробкою — регулярні білди та замір розміру через Build Report. Unity Profiler працює для WebGL через Development Build + удалене профілювання з редактора.
QA на цільових платформах. Обов'язково: реальний мобільний Safari, реальний Chrome на Android mid-range пристрої. Емулятори в DevTools не відтворюють реальне споживання пам'яті та GPU throttling.
Деплой. Nginx з правильними MIME-типами (.wasm → application/wasm, .data → application/octet-stream) та Brotli/gzip. CDN для статики — завантаження ассетів з edge-ноди замість origin істотно знижує час до першого кадру.
Терміни — від 1-2 тижнів для простих казуальних ігр до 2 місяців для мідкор-проектів з мультиплеєром та складною інтеграцією. Вартість розраховується після аналізу ТЗ.





