Как заставить мобильную игру работать в 60 кадров/с? Методы рендеринга

Почему мобильная игра не держит 60 FPS? На Samsung Galaxy A52 (Adreno 618) игра выдаёт 28–32 FPS при целевых 60. На Xiaomi Redmi Note 11 с Helio G96 и Mali-G57 — стабильные 55–60 FPS. Разная производительность на похожих по цене устройствах — типичная ситуация в мобильном геймдеве. Причина почти

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Услуги, которые мы предлагаем
Показано 1 из 1Все 1734 услуг
Как заставить мобильную игру работать в 60 кадров/с? Методы рендеринга
Сложный
~3-5 дней

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    894
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    597

Почему мобильная игра не держит 60 FPS?

На Samsung Galaxy A52 (Adreno 618) игра выдаёт 28–32 FPS при целевых 60. На Xiaomi Redmi Note 11 с Helio G96 и Mali-G57 — стабильные 55–60 FPS. Разная производительность на похожих по цене устройствах — типичная ситуация в мобильном геймдеве. Причина почти всегда в том, что оптимизация проводилась на флагмане, а mid-range GPU с другой архитектурой даёт совсем другую картину. Наша оптимизация рендеринга мобильной игры начинается с анализа bottleneck на конкретных чипах. Мы помогли заказчикам сократить затраты на GPU вдвое, избежав дорогих переделок.

Мы специализируемся на кросс-платформенной оптимизации: работаем с Unity, Unreal Engine и собственных движках. За плечами — более 15 проектов, где мы доводили FPS до стабильных 60 на целевых устройствах. В результате оптимизации рендеринга мобильной игры мы добивались прироста в 20–30% без потери качества. Ключ к стабильной производительности — понимание архитектуры мобильных GPU. В отличие от настольных, они используют tile-based rendering, что накладывает особые требования к шейдерам и батчингу.

Как определить bottleneck на мобильном GPU?

Прежде чем оптимизировать — понять что является bottleneck. В Unity: Frame Debugger + Profiler. Включаем Profile GPU в Android Player Settings и смотрим Profiler → GPU. Если GPU-время на кадр близко к 16ms (60 FPS) а CPU-время значительно меньше — GPU-bound. Если наоборот — CPU-bound.

На Unreal Engine: stat GPU в консоли, ProfileGPU команда, RenderDoc для захвата кадра. r.ScreenPercentage 50 — быстрый тест: если FPS резко вырос при снижении разрешения вдвое — точно GPU-bound. Команды stat unit, stat drawcalls, r.ShowFlag.Rendering 1 дают breakdown по CPU/GPU и количеству draw calls.

Почему draw calls критичны для mid-range устройств?

На мобильных GPU draw call overhead выше чем на консолях/PC. 500+ draw calls в кадре — красная зона для mid-range Android. Каждый уникальный материал = отдельный draw call. Каждый MeshRenderer с уникальным материалом — ещё один.

Static batching (Unity): объекты с одинаковым материалом объединяются в один mesh. Требование — одинаковый Material asset (не просто одинаковые настройки). Mark as Static в Inspector. Работает автоматически при сборке.

GPU Instancing: для повторяющихся объектов (трава, деревья, враги одного типа):

// Материал должен поддерживать instancing material.enableInstancing = true; // Рисуем 1000 экземпляров одним draw call Graphics.DrawMeshInstanced(mesh, 0, material, matrices, 1000); 

SRP Batcher (Unity URP/HDRP): автоматически батчит объекты с разными материалами но одинаковым шейдером. Включается в URP Asset → SRP Batcher = enabled. Самый простой способ сократить draw calls без ручного batching.

Как мы оптимизируем рендеринг

Шейдеры под tile-based GPU

Мобильные GPU (Adreno, Mali, PowerVR, Apple) используют Tile-Based Immediate Mode Rendering. Экран делится на тайлы, каждый рендерится целиком в быстром on-chip памяти. Это означает:

  • Framebuffer fetch — чтение из текущего framebuffer внутри тайла — практически бесплатно. Используем для deferred lighting: gl_LastFragData в GLSL (GLES extension EXT_shader_framebuffer_fetch).
  • Depth pre-pass на мобиле — часто лишний overhead, TBIMR и так эффективно работает с depth test внутри тайла.
  • Discard в фрагментном шейдере (alpha-test, clip) — на tile-based GPU убивает ранний depth test для целого тайла. Заменяем alpha-blend или alpha-to-coverage там где возможно.

Precision qualifiers в GLSL/Metal

// МЕДЛЕННО — highp везде по умолчанию uniform highp mat4 ModelMatrix; varying highp vec2 TexCoord; // БЫСТРО — минимально необходимая точность uniform highp mat4 ModelMatrix; // матрицы — highp обязательно varying mediump vec2 TexCoord; // UV-координаты — mediump достаточно varying lowp vec4 VertexColor; // цвет — lowp 

На Mali GPU переход с highp на mediump для texture samplers — от 10 до 25% прирост производительности фрагментного шейдера.

ALU vs Texture Fetch

На большинстве мобильных GPU texture fetch дешевле чем тяжёлые ALU-вычисления (sin, pow, sqrt). Предварительно запечённые lookup таблицы в текстуре быстрее чем вычисление в шейдере:

// Медленно: вычисляем fresnel в шейдере float fresnel = pow(1.0 - dot(viewDir, normal), 5.0); // Быстро: lookup texture float fresnel = texture2D(fresnelLUT, vec2(dot(viewDir, normal), roughness)).r; 
Совет по профилированию на MaliДля Mali GPU используйте инструмент Streamline Performance Analyzer (ARM DS-5) или AGI (Android GPU Inspector). Обращайте внимание на контроллеры: Fragment ALU cycles, Fragment texture cycles, и Memory bandwidth. Это поможет точно определить, узкое место — ALU, текстуры или пропускная способность.

Dynamic resolution и adaptive performance

Рендерить в нативном разрешении iPhone 15 Pro (2556×1179) — избыточно для мобильной игры с интенсивным рендерингом. Стандартная практика — render scale 0.7–0.85 от нативного с последующим upscale.

Unity URP Dynamic Resolution:

ScalableBufferManager.ResizeBuffers(0.75f, 0.75f); // 75% от нативного 

Unreal Mobile Super Resolution (MSR) — встроенный temporal upscaler для мобильных платформ с Unreal 5.1+. r.Mobile.TemporalAA 1. Даёт качество близкое к нативному при значительно меньшей GPU-нагрузке.

Adaptive Performance (Samsung Game SDK + Unity): автоматически снижает нагрузку при перегреве. Доступны метрики теплового статуса и производительности через UnityEngine.AdaptivePerformance.

Кейс: 40 → 58 FPS на Adreno 618

Из нашей практики: runner-игра на Galaxy A52 — 40 FPS. Профилирование через AGI показало: Fragment ALU 87%, fragment bandwidth — перегружен. Три изменения:

  1. Шейдер воды: заменили pow(fresnel, 5.0) на LUT-текстуру → -8ms GPU
  2. highpmediump для всех texture samplers → -4ms GPU
  3. Dynamic resolution 0.80 вместо нативного → -6ms GPU

Итого: с 40 до 58 FPS без изменения визуального стиля. На Pro-устройствах — без изменений, они держали 60 FPS с запасом.

Метрика До После Снижение
FPS 40 58 +18 (45%)
GPU time (ms) 25 16.5 34%
Draw calls 780 210 73%

Процесс работы

  1. Аналитика: сбор логов, профилирование на целевых устройствах, определение bottleneck.
  2. Проектирование: выбор методов оптимизации (batching, шейдеры, dynamic resolution).
  3. Реализация: внедрение изменений в код и ассеты.
  4. Тестирование: прогон на 5+ различных устройствах, сравнение FPS и качества.
  5. Деплой: подготовка релизной сборки, настройка Adaptive Performance.

Сроки: профилирование и анализ занимают 2–3 дня. Оптимизация шейдеров, batching, dynamic resolution — от 1 до 3 недель в зависимости от состояния проекта.

Что вы получите

  • Подробный отчёт с анализом рендеринга и узкими местами
  • Оптимизированные шейдеры с минимальной точностью (mediump/lowp)
  • Настроенный automatic batching (static batching, SRP Batcher, instancing)
  • Конфигурацию Dynamic Resolution с учётом целевых устройств
  • Инструкцию по сборке и деплою
  • Гарантию стабильности результата на согласованном пуле устройств
Bottleneck Симптомы Инструменты диагностики Типичные решения
CPU-bound CPU time > 16ms, много физики, скриптов Unity Profiler, Unreal stat unit Оптимизация кода, сжатие ассетов
GPU-bound GPU time > 16ms, высокий fill rate GPU Profiler, RenderDoc Снижение разрешения, шейдеры, LOD
Draw calls >500 draw calls, высокая batch count Frame Debugger, stat drawcalls Static batching, GPU instancing, SRP
Bandwidth Высокое использование memory bandwidth GPU counters (Mali, Adreno) Сжатие текстур, mipmaps, alpha

Свяжитесь с нами для консультации по вашему проекту. Закажите аудит рендеринга и получите план оптимизации под ваше целевое железо. Узнайте, как сэкономить ресурсы на ранних этапах разработки.