Як оптимізувати фізичний рушій для мобільних ігор?
Ми часто стикаємося з ситуацією: гра з достовірною фізикою на Unity падає до 15 FPS на Snapdragon 680 через хвилину після запуску. Повноцінна симуляція PhysX або Bullet в 120 Гц — непозволительная розкіш для мобільного CPU. Тому наш підхід — шукати компроміс між достовірністю та продуктивністю для кожного жанру. Ми на ринку з 2015 року, реалізували понад 30 мобільних ігор з кастомною фізикою, тому знаємо, як зекономити до 30% бюджету на розробку. Зв'яжіться з нами — оцінимо ваш проект і запропонуємо оптимальну архітектуру.
Фіксований timestep і його ціна
Unity оновлює фізику в FixedUpdate з інтервалом Time.fixedDeltaTime (за замовчуванням 50 Гц). На мобільному пристрої, що працює в 30 FPS, це означає два фізичних кроки на кадр. Якщо гра йде в 20 FPS через тепловий захист, Unity робить 2-3 кроки PhysX за один відмальований кадр — CPU навантаження зростає нелінійно. Згідно з документацією Unity, FixedUpdate викликається з фіксованим інтервалом, але на слабких пристроях це може призводити до просадок.
Оптимальна стратегія: знижувати Fixed Timestep до 0.033 (30 Гц) для мобільних білдів і компенсувати це точнішими колайдерами. Для ігор, де фізика не критична для геймплею (пазли, гіперкежуал), можна опустити до 0.05 (20 Гц) і інтерполювати позиції об'єктів візуально через Rigidbody.interpolation = RigidbodyInterpolation.Interpolate. Ми маємо великий досвід у мобільному геймдеві — перебрали десятки конфігурацій і добилися зниження CPU навантаження на фізику до 40%.
Коли PhysX надлишковий
Для 2D-ігор на Unity вбудована фізика Box2D (через Rigidbody2D, Physics2D) значно легша за PhysX. Але навіть Box2D на 200+ динамічних об'єктах починає тиснути на CPU. У Godot 4 аналогічно — RigidBody2D + GodotPhysics2D ефективніше, ніж 3D-фізика для плоских ігор.
Для гіперкежуал і аркадних механік часто вигідно повністю відмовитися від рушійного фізичного двигуна і написати детерміновану фізику вручну:
// Спрощена фізика стрибка без Rigidbody void Update() { if (isGrounded && Input.GetTouch(0).phase == TouchPhase.Began) velocity.y = jumpForce; velocity.y -= gravity * Time.deltaTime; transform.position += velocity * Time.deltaTime; if (transform.position.y <= groundLevel) { transform.position = new Vector3(transform.position.x, groundLevel, 0); velocity.y = 0; isGrounded = true; } } Детермінована фізика передбачувана, дебажиться одним дотиком і працює однаково на будь-якому пристрої. Для мультиплеєрних ігор це ще й гарантія синхронізації станів.
Як написати детерміновану фізику: покрокове керівництво
- Визначте необхідні властивості: гравітація, швидкість, прискорення.
- У кожному кадрі оновлюйте позицію через
transform.position += velocity * Time.deltaTime. - Обробляйте колізії простими перевірками (наприклад, по межах екрану).
- Для взаємодії об'єктів використовуйте мінімальні обчислення без фізичного двигуна.
Такий підхід дозволяє досягти 60 FPS на бюджетних пристроях навіть із сотнею об'єктів.
Чому кастомна фізика іноді вигідніша?
Взаємодія об'єктів: де зазвичай ламається
Стекування об'єктів PhysX погано симулює стопки з 10+ динамічних об'єктів на мобільному залізі — починається джиттер і об'єкти «провалюються» крізь один одного. Рішення: Rigidbody.maxDepenetrationVelocity знижувати до 1-3 м/с (замість default 10), Physics.defaultSolverIterations до 4-6 (default 6), Physics.defaultSolverVelocityIterations до 1.
Тонкі колайдери та туннелювання Швидкі об'єкти — кулі, снаряди — на низькому FPS за один крок можуть пролетіти крізь тонку стіну. Rigidbody.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic вирішує проблему, але вдвічі дорожче по CPU. Альтернатива: для снарядів використовувати raycast замість фізичного тіла — Physics.SphereCast з радіусом снаряда від попередньої позиції до поточної.
Продуктивність на різних пристроях
Реальна картина з профайлера (Unity Profiler + Android Profiler) в проекті з 3D-аркадою (80 фізичних об'єктів, Snapdragon 665):
| Конфігурація | Fixed Timestep | CPU на фізику | FPS |
|---|---|---|---|
| Default PhysX | 50 Гц | 4.2 мс/кадр | 38 |
| Reduced iterations | 30 Гц | 2.1 мс/кадр | 56 |
| Кастомна фізика | N/A | 0.6 мс/кадр | 60 |
Кастомна фізика — для конкретного жанру, а не універсальне рішення. Але коли ігрова механіка це дозволяє, виграш очевидний. Наприклад, кастомна фізика в 7 разів швидше за PhysX на бюджетних пристроях, а Box2D в 2 рази продуктивніше PhysX для 2D. Ми спроектували десятки мобільних ігор з різними фізичними підходами — від аркад до симуляторів.
Порівняння популярних рушіїв:
| Рушій | Платформа | Продуктивність | Детермінізм | Рекомендація |
|---|---|---|---|---|
| Box2D | 2D | Середня | Так | Для 2D-ігор до 200 об'єктів |
| PhysX | 3D | Висока | Ні | Для 3D з потужними пристроями |
| Кастомна фізика | Будь-яка | Максимальна | Так | Для гіперкежуал і мультиплеєра |
Фізика в React Native і Flutter іграх
Для React Native гра пишеться або на Godot з експортом в Web/Android, або через рушій на JavaScript (Phaser.js через WebView). Phaser використовує Matter.js для 2D-фізики — він легший за Box2D по споживанню пам'яті, але поступається в точності. Matter.Runner.run() з fps: 30 на більшості Android-бюджетників достатньо.
Для Flutter + flame: forge2d (порт Box2D на Dart) дає повноцінну 2D-фізику. World.stepDt викликається в game.update(dt), частота оновлень контролюється ігровим лупом flame. Критично: forge2d працює в метрах, а flame — в пікселях. Коефіцієнт перерахунку (worldScale) потрібно задати один раз і дотримуватися його всюди.
Коли варто використовувати кастомну фізику
Кастомна фізика виправдана, якщо: гра містить унікальні механіки (гумові об'єкти, деформації), потрібен детермінізм для мультиплеєра, або стандартні рушії не забезпечують потрібний FPS на цільових пристроях. У таких випадках кастомне рішення може знизити вартість розробки на 20-30% за рахунок відсутності ліцензійних відрахувань та оптимізації під конкретні механіки.Вибір фізичного рушія мобільної гри: ключові параметри
При виборі фізичного рушія для мобільної гри важливо враховувати інерційні властивості об'єктів, тензор інерції, коефіцієнт відновлення, а також алгоритми виявлення колізій (Sweep and Prune, GJK, EPA). Для гіперкежуал ігор часто достатньо спрощеної моделі з низькою в'язкістю та жорсткістю, що дозволяє досягти максимальної продуктивності.
Що входить в роботу
- Аналіз механік і профілювання цільових пристроїв
- Вибір фізичного рушія або проектування кастомного рішення
- Розробка і налаштування фізичних взаємодій
- Оптимізація під низькопродуктивні пристрої (троттлінг, теплозахист)
- Інтеграція з аналітикою та crash-репортами
- Документація по конфігах і підтримка при релізі
Процес роботи
Починаємо з профілювання цільових пристроїв — бюджетний Android і топовий iPhone дають різну картину. Вибираємо фізичний рушій або кастомну реалізацію виходячи з жанру, кількості об'єктів і цільового FPS. Пишемо фізичні взаємодії, профілюємо в реальних умовах (throttle mode, без зарядки), ітеруємо.
Типові терміни: базові фізичні взаємодії — 1-2 тижні, складні системи (руйновані об'єкти, гнучкі тіла, fluid simulation) — 3-6 тижнів. Вартість розраховується індивідуально після аналізу механік. Отримайте консультацію по архітектурі фізики вашої гри — зв'яжіться з нами.







