Створення браузерних ігор на WebGL: від прототипу до деплою
Клієнт приходить із прототипом на Unity: гра відмінно працює в редакторі, але після збірки в WebGL браузер видає Out of Memory або завантаження триває 30 секунд. Згідно з дослідженнями, 40% користувачів покидають сторінку, якщо час завантаження перевищує 3 секунди. WebGL — це 256 МБ пам'яті за замовчуванням, один потік, відсутність доступу до файлової системи та Safari зі своїми quirks. Ми займаємося розробкою WebGL-ігор під ключ із 2014 року. За 10+ років виконали понад 50 проєктів: гіпер-казуальні ігри для маркетингу, освітні симулятори, інтерактивні 3D-презентації. Наш досвід показує: без глибокої оптимізації проєкт не запуститься у половини аудиторії. Ми допомагаємо пройти шлях від прототипу до деплою, гарантуючи стабільну роботу на всіх цільових браузерах.
Чим 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, але пам'ятаємо: це резервується одразу при завантаженні сторінки, незалежно від фактичного використання. Скорочення draw calls на 30% за рахунок batching та occlusion culling також знижує навантаження на пам'ять.
Як боротися з обмеженням пам'яті в WebGL?
Відсутність багатопоточності та workarounds
WebAssembly threading потребує SharedArrayBuffer, який заблоковано на більшості хостингів без правильних CORS-заголовків (Cross-Origin-Opener-Policy: same-origin + Cross-Origin-Embedder-Policy: require-corp). На практиці threading вмикаємо тільки якщо контролюємо сервер.
Без threading всі завдання — фізика, анімації, аудіо-декодування — виконуються в головному потоці. Це обмеження змушує інакше думати про архітектуру:
- Coroutines з yield замість важких Update() циклів — дозволяє розмазати обчислення по кадрах.
- Burst Compiler у WebGL працює і без threading — компілює гарячі шляхи в SIMD-оптимізований wasm, знижуючи час виконання на 20-40%.
- Алгоритми з O(n²) складністю, які непомітні на PC, вбивають framerate в браузері.
Як зменшити розмір білда та час завантаження?
Стандартний Unity WebGL білд без оптимізації важить 30-60 МБ (gzip). Користувач чекає завантаження — і йде. Оптимізуємо:
- 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 секунд. Економія бюджету на хостинг склала 40% за рахунок меншого трафіку.
| Оптимізація | Ефект |
|---|---|
| Code Stripping High | −5..15 МБ |
| Brotli стиснення | −15..20% розміру |
| Addressables | час завантаження −50% |
| Crunch стиснення текстур | −40..60% пам'яті |
Чому WebGL-гра може не працювати на Safari?
Safari реалізує WebGL інакше, ніж Chrome, і не підтримує threading. Також відрізняється робота з пам'яттю: на iOS WebGL-контекст може бути скинутий при нестачі ресурсів. Ми тестуємо на реальних пристроях за допомогою BrowserStack та LambdaTest, щоб гарантувати сумісність. Замовте аудит вашого WebGL-проєкту — ми виявимо вузькі місця та запропонуємо рішення.
Що входить в нашу роботу
- Аналіз вимог та цільових браузерів
- Архітектура ассетів з Addressables
- Розробка та оптимізація під WebGL
- QA на реальних пристроях
- Деплой з правильними MIME-типами та CDN
- Документація по збірці та підтримці
Стек та інструменти
Двигун: Unity актуальної LTS, 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, платіжні системи, analytics) — власна JS-обгортка поверх Unity.
Мультиплеєр у WebGL: WebSocket замість UDP. Mirror з Transport SimpleWebTransport — працює через WSS. 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 місяців для мідкор-проєктів з мультиплеєром та складною інтеграцією. Вартість розраховується індивідуально після аналізу ТЗ.
Зв'яжіться з нами — оцінимо ваш проєкт безкоштовно та запропонуємо оптимальну стратегію розробки.






