Разработка игр на WebGL
Клиент хочет игру, которая запускается по ссылке — без установки, без апп-стора, прямо в браузере. Звучит просто. На деле 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²) сложностью, которые незаметны на PC, убивают 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, платёжные системы, analytics) — собственная 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 месяцев для мидкор-проектов с мультиплеером и сложной интеграцией. Стоимость рассчитывается после анализа ТЗ.





