Оптимизация потребления батареи мобильной игрой
Игра, которая разряжает телефон за полтора часа, получает однозвёздочные отзывы — даже если FPS стабильный и крэшей нет. Отзывы «садит батарею» в App Store и Google Play напрямую влияют на конверсию установок. При этом потребление энергии — это прямое следствие того, насколько эффективно используются вычислительные ресурсы.
Откуда берётся лишнее потребление
Неограниченный FPS. Самая распространённая ошибка. Application.targetFrameRate = -1 (или без явной установки) означает, что Unity рендерит так быстро, как может. На iPhone 15 Pro это 120 FPS в простом меню. Для меню достаточно 30 FPS — оставшиеся 70% CPU/GPU-времени тратятся впустую и греют корпус.
Частицы и эффекты в фоне. Анимированный фон в главном меню с 500 частицами работает постоянно, даже когда пользователь смотрит на пуш-уведомление. Нет паузы при потере фокуса приложения — нет экономии.
GPS, акселерометр, другие сенсоры. Если игра запрашивает Input.location или Input.gyro без необходимости, а разработчик забыл отключить — сенсоры опрашиваются постоянно. На Android это несколько мВт дополнительно.
Сетевые запросы без батчинга. Маленькие HTTP-запросы каждые 5–10 секунд (аналитика, heartbeat, синхронизация) держат радиомодуль в активном состоянии. Радио — один из самых энергоёмких компонентов телефона.
Управление FPS по контексту
Правильная стратегия — разные таргеты для разных состояний:
// Gameplay: максимальное качество
Application.targetFrameRate = 60;
// Меню, паузы, диалоги
Application.targetFrameRate = 30;
// Фоновые вычисления (загрузка, сохранение)
Application.targetFrameRate = 15;
На iOS нужно также учитывать ProMotion-дисплеи (120 Hz на iPhone 13 Pro+). По умолчанию Unity работает на 60 FPS даже на 120 Hz экране, но явно устанавливать CADisplayLink.preferredFrameRateRange через Native Plugin стоит, если нужна более тонкая настройка.
OnApplicationPause(true) — здесь снижаем FPS до минимума или останавливаем рендер полностью.
Эффективность шейдеров
На мобильных GPU важна точность вычислений. Использование half вместо float в шейдерах на Adreno и Mali даёт реальную экономию энергии, потому что ALU на этих чипах оптимизированы под half-precision. Для большинства игровых эффектов (цвет, UV, освещение) точности half достаточно.
Сложные фрагментные шейдеры с большим количеством текстурных выборок особенно дороги. Каждое tex2D — это обращение к памяти с латентностью, которое может остановить конвейер. Запекание лайтмап вместо динамического освещения сокращает нагрузку на фрагментный шейдер.
Батчинг сетевых запросов
Вместо отправки игровых событий аналитики по одному — буферизация и отправка пачкой раз в минуту. Firebase Analytics делает это автоматически. Если используется собственная аналитика через HTTP — явный RequestQueue с таймером.
На Android WorkManager с setRequiresBatteryNotLow(true) позволяет откладывать некритичные запросы до момента, когда устройство на зарядке.
Проверка результата
iOS: Xcode Energy Organizer + MetricKit. MXCPUMetric и MXGPUMetric в didReceive дают реальные данные о потреблении из отчётов реальных пользователей (агрегированно, без PII).
Android: Android Vitals в Play Console → Battery → Excessive wakeups. Если приложение будит устройство чаще 10 раз в час в фоне — это флаг от Google, который влияет на видимость в поиске.
Для локального тестирования — adb shell dumpsys batterystats --reset перед тестом и adb shell dumpsys batterystats после. Показывает детальную разбивку по компонентам.
Сроки оптимизации: три-пять рабочих дней, зависит от количества проблемных мест и наличия нативных плагинов.







