Создание мобильной игры на Unity: примеры и этапы
Почему Unity — оптимальный выбор для мобильных игр
Unity — один из немногих движков, объединивших в себе масштабируемость, гибкость и простоту, достаточную даже для первого проекта, который реально довести до релиза. Создание мобильной игры на Unity выгодно отличается от работы с другими движками: в отличие от Unreal Engine, больше ориентированного на графически насыщенные проекты, Unity не перегружен системами, не нужными мобильной игре. Godot подходит для небольших 2D-экспериментов, но пока что страдает от недостатка поддержки и зрелой экосистемы.

Платформа поддерживает Android и iOS из коробки: прямо из одного интерфейса вы можете собирать .apk и .ipa-файлы. Встроенные инструменты импорта SDK, настройка ориентации экранов и плотностей пикселей уменьшают количество ручной работы. Это особенно важно, когда вы хотите быстро получить рабочий билд для тестирования. Кроме того, Unity — кроссплатформенный: один и тот же проект играет одинаково на смартфоне, планшете или в WebGL-версии на сайте.
Asset Store — это ключевой актив. Механика свайпа, генератор уровней, заготовка UI — всё это покупается (или скачивается бесплатно) и адаптируется под проект. Компонентная архитектура позволяет добавлять или отключать функции по необходимости. Даже при первом опыте разработки вы можете создать работающий проект с игровым процессом, прогрессией и меню, не написав тысячу строк с нуля.
Но Unity не лишён ограничений. Если цель — гиперкачественная 3D-игра с рейтрейсингом и обилием VFX, оптимизация под смартфоны потребует серьёзной переработки. Или если ваша задача — минимальный билд под веб с размером менее 5 МБ, Unity может быть «тяжеловат» из-за зависимости от C#-рантайма.
Пример: один человек может сделать за 5 дней простую 2D-аркаду — клон Flappy Bird или Match-3 с базовой системой очков. Движок предоставляет физику, обработку касаний, текстуры, систему сцен, переходов между ними и даже поддержку рекламы через встроенные плагины.
Что нужно решить до начала разработки (архитектура идеи)
Игра — это не набор скриптов, а целостный проект с избранным жанром, режимами игры, визуальным стилем, аудиторией и каналами дистрибуции. Решения на этом этапе определяют: какие механики вы реализуете, хватит ли ресурсов, и будет ли ваш файл играться на дешёвом Android-смартфоне так же, как на iPhone 13.
Жанр: фундамент для конструктора вашей игры
Выбор жанра — это не просто «будет платформер». Это определяет поведение игроков, подход к монетизации и интерфейс. Например:
- Hyper-casual (сплитер, раннер, кликер) — короткие сессии, минималистичный UI, высокая частота рекламы. Простая механика повторяется много раз.
- Mid-core (карточные бои, tower defense, RPG) — требуют систем прогрессии, баланса игровых характеристик, кучи UI-компонентов.
- Match-3 или puzzle — сильная зависимость от контента, уровней, а не только механики. Используется генерация карт или дизайнер из уровней.
Жанр влияет даже на ритм скриптов в игре: кликеры работают по интервалам, шутеры — на кадровой синхронизации, головоломки — по «ходам» игрока.
Графика: 2D или 3D — это не просто вкус
2D-игра быстрее в разработке и потребляет меньше ресурсов. Вам достаточно спрайтов, Canvas-интерфейса и минимального количество кодов для движений. 3D-проект потребует сложных моделей, освещения, камеры, физики и, чаще всего, проблем с производительностью. Даже у мощных смартфонов draw call’ы в Unity могут «падать» на обилии объектов.
Базовый ориентир — если вы делаете игру с фронтальной камерой (при виде сбоку), выбирайте 2D. Если планируется свободное перемещение по сцене, применим 3D.
Платформы и устройства: ограничения, которые нельзя игнорировать
Минимальный уровень Android SDK (обычно от API 21 для 95% устройств). Разрешение экрана варьируется от 480×800 до 2560×1440+, и если не тестировать ширину пикселизации, интерфейс съезжает. ОЗУ и процессор зависят от класса устройства: low-end теряет кадры при анимации UI, если вы используете нескомпрессированные текстуры.
Проверка идеи через аналог: хотите сделать аналог Subway Surfers? Вам потребуется:
- 3D-анимации с автоматической генерацией препятствий
- Поддержка динамического ландшафта
- Фиксированная камера со скриптом следования
- Система разблокировки героев / бонусов (т.е. файловая система для прогресса)
Проверить реальность проекта можно буквально за 30 минут: нарисуйте набросок экрана, опишите механику словами и примерьте это под палец на смартфоне. Если управление выглядит сложно — стоит упростить.
Не пишите код, пока не решили это
Главная ошибка новичков — старт скриптов без продуманной архитектуры. В результате проект превращается в сочетанную кашу из вызовов Update, событий, случайно связанных переменных. Стратегия «сыграем, посмотрим» работает только в геймдизайне, но не в коде.
Сначала ответьте себе:
- Что запускается первым? (Меню, туториал, уровень?)
- Как сцены связаны между собой?
- Есть ли необходимость в системе сохранений?
- Какие данные переходят между сценами?
Установка Unity и настройка окружения под мобильную разработку
Работать с Unity без корректной среды — всё равно что собирать мебель без отвертки. Начать стоит с установки Unity Hub — официального лаунчера, где вы можете управлять проектами, версиями и плагинами под Android/iOS.
Выбор правильной версии
Для мобильной разработки лучше использовать LTS-релиз (Long Term Support), который обновляется без радикальных изменений. Например, Unity 2022.3 LTS — стабильна, совместима со всеми ключевыми пакетами и предоставляет поддержку минимум 2 года. Актуальные версии могут иметь критические ошибки или несовместимости с Android SDK.
Пошаговая настройка:
- Скачайте Unity Hub и установите LTS-релиз с модулями Android Build Support и iOS Build Support.
- Создайте проект, выбрав шаблон 2D или 3D в зависимости от концепта.
- Перейдите в File → Build Settings, выберите Android или iOS.
- Для Android — убедитесь, что установлен Android SDK & NDK. Unity предлагает автоматическую установку, но иногда лучше задать путь вручную.
- Для iOS (macOS only) — наличие Xcode обязательно (минимум версии 14).
Типичные проблемы новичков при сборке:
- Android build failed — чаще всего отсутствует либо SDK, либо исправные пути к нему. Решается указанием вручную: Edit → Preferences → External Tools.
- Could not produce a signed APK — не создан ключ подписи. Для теста можно использовать debug-ключ, но в Play Store нужен production-ключ.
Один раз правильно настроенная сборка экономит десятки часов в будущем. Сохраняйте пути и конфигурации в IDE-шных .json-файлах, чтобы не настраивать каждый раз заново.
Построение базовой структуры мобильной игры
Ошибочно воспринимать игровой проект как цепочку сцен или набор единичных скриптов. Для стабильной и масштабируемой мобильной игры на Unity необходимо задать архитектуру с чётким разделением ответственности между системами, а не писать всю логику в Player.cs. В этом разделе рассмотрим, как правильно «скелетировать» игру: выбрать сцены, менеджеры, UI-компоненты и подготовить проект к расширению без хаоса в коде.
Из чего состоит базовая структура мобильной игры
Мобильная игра, вне зависимости от жанра, как правило, состоит из следующих элементов:
- Game Manager — центральный контроллер, запускающий логику уровня, отслеживающий состояние игры, переходы, инициализацию.
- UI Manager — система управления интерфейсом, отвечающая за отображение очков, различных окон, паузы и экрана проигрыша.
- Scene Loader — отдельный скрипт, обрабатывающий переходы между сценами без дублирования кода.
- Spawn System (если применимо) — отвечает за генерацию платформ, врагов, бонусов или других игровых объектов.
- Input Manager — изолирует управление: свайпы, касания, удержания экрана.
Каждая из этих систем находится в своём скрипте или даже «слое» префабов. Это упрощает отладку: если вы замечаете сбой при респавне врагов, не нужно разбираться в UI-логике. Нарушение этих границ — частая причина сложных багаутов: всё работает странно, но непонятно где.
Структура, которую можно взять за основу
Допустим, вы разрабатываете 2D-раннер. Структура папок и компонентов может выглядеть следующим образом:
- Scripts/ManagersGameManager.cs
- UIManager.cs
- SceneLoader.cs
- Scripts/GameplayPlayerController.cs
- ObstacleSpawner.cs
- ScoringSystem.cs
- UI/PrefabsHUDCanvas.prefab
- ButtonStart.prefab
- PauseMenu.prefab
- ScenesMainMenu.unity
- GameScene.unity
- GameOver.unity
Такой подход не просто упрощает чтение проекта в Unity, но и уменьшает когнитивную нагрузку: вы знаете, где искать проблему.
Раздельная логика: почему избегать «монолитных» скриптов
Один из распространённых анти-паттернов — вложить всё внутрь Player.cs: обработку касания, движение, обновление UI, проверку столкновений. В краткосрочной перспективе это работает, но любой апдейт превращается в часы исправлений, ведь каждое изменение цепляет остальное.
Правильная стратегия — делить логику на модули и использовать события. Например, при касании игрока объект может сработать триггер, отправив Event в GameManager, который увеличивает счёт и обновляет UI через UIManager. Один каскад, но всё по слоям.
Поддержка экранов и адаптация под плотности пикселей
Одна из самых недооценённых, но критичных задач — обеспечение корректного отображения интерфейса на всех современных девайсах. От iPhone SE до Xiaomi Redmi Note 12.
Unity Canvas предлагает следующие режимы рендеринга:
- Screen Space – Overlay — по умолчанию. Удобен в простых проектах.
- Screen Space – Camera — даёт больше контроля при масштабировании элементов, особенно в 3D.
Добавьте к Canvas компонент Canvas Scaler и используйте режим Scale With Screen Size. Рекомендуемые параметры:
- Reference Resolution: 1080×1920
- Match (Width or Height): 0.5 — сбалансированный компромисс
Это решение позволяет избежать ситуации, когда кнопка «Начать игру» уезжает за пределы экрана на маленьких устройствах или визуально крошечна на планшетах.
Мини-пример: стартовая сцена с кнопкой «Начать игру»
- Создайте новую сцену MainMenu.unity
- Добавьте Canvas, задайте Canvas Scaler → Scale With Screen Size
- Добавьте UI → Button, назовите её StartButton
- Создайте скрипт MainMenuController.cs:
using UnityEngine;
using UnityEngine.SceneManagement;
public class MainMenuController : MonoBehaviour
{
public void StartGame()
{
SceneManager.LoadScene("GameScene");
}
}
- Назначьте этот скрипт на пустой GameObject
- На кнопке в OnClick добавьте ссылку на этот объект → метод StartGame()
Теперь при нажатии кнопки сцена переключится — без одной строки лишнего кода в другом месте.
Реализация ключевой механики (игровой процесс: шаг за шагом)
Теперь — к самому важному: сделать так, чтобы игрок чувствовал контакт с игрой. Независимо от жанра, вы реализуете сбор ввода, динамику объектов, взаимодействие между ними и логику результата (победа/поражение). Здесь мы разберём базовый пример endless runner с боковым видом: та же механика, что в Subway Surfers или Jetpack Joyride.
Игровой цикл в Unity: основная логика
Unity предоставляет событийные методы, на которых строится логика:
- Start() — инициализация объекта
- Update() — вызывается каждый кадр (~60 раз в секунду)
- FixedUpdate() — вызывается с фиксированной частотой, применим для физики
- OnCollisionEnter2D/3D — обработка столкновений
Все они работают внутри MonoBehaviour, но важно: избегайте загромождения большого количества логики в Update() одного объекта. Лучше передавайте события через делегаты или UnityEvents.
Пример: реализация endless runner на минимуме
Основные составляющие:
- Игрок — перемещается по вертикали (прыжки) или дорожкам (влево/вправо)
- Препятствия — движутся навстречу игроку
- Очки — увеличиваются по времени или за преодоление препятствий
Создадим скрипт для авто-передвижения игрока:
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float jumpForce = 7f;
private Rigidbody2D rb;
private bool isGrounded = true;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
if (Input.GetMouseButtonDown(0) && isGrounded)
{
rb.velocity = Vector2.up * jumpForce;
isGrounded = false;
}
}
private void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.CompareTag("Ground"))
isGrounded = true;
}
}
Объекты-платформы и пол помещаются на слой Ground. Игрок распознаёт столкновение и разрешает повторный прыжок.
Спавн препятствий в сцене
Создайте скрипт ObstacleSpawner.cs с автогенерацией объектов через интервалы времени:
using UnityEngine;
public class ObstacleSpawner : MonoBehaviour
{
public GameObject obstaclePrefab;
public float spawnRate = 2f;
private float timer = 0f;
void Update()
{
timer += Time.deltaTime;
if (timer >= spawnRate)
{
SpawnObstacle();
timer = 0f;
}
}
void SpawnObstacle()
{
Instantiate(obstaclePrefab, transform.position, Quaternion.identity);
}
}
Этот скрипт размещается на точке за пределами видимости справа, чтобы препятствия появлялись и двигались внутрь камеры. Для движения препятствий добавьте к prefab’у простой скрипт:
public class MoveLeft : MonoBehaviour
{
public float speed = 5f;
void Update()
{
transform.Translate(Vector2.left * speed * Time.deltaTime);
if (transform.position.x < -15f)
Destroy(gameObject);
}
}
Это решение обрабатывает 95% случаев для начала. Вы можете впоследствии добавить выборку препятствий из массива, инкрементальную скорость, уровни сложности.
Разделение механики и визуала
Даже если кажется, что проще объединить анимацию и действие — не делайте этого. Например, когда игрок сталкивается с препятствием, пусть физика обрабатывает это, а GameManager только реагирует: отправляет сигнал проигрыша, запускает анимацию, останавливает спавн. Отделение слоёв — гарантия, что вы можете заменить визуальную часть без переписки логики.
Отладка: как диагностировать поведение
- Debug.Log() — непревзойдённо простой инструмент. Помечайте ключевые действия: прыжок, столкновение, удаление объекта.
- Gizmos — используйте для отрисовки границ коллайдеров и движения объектов в редакторе.
- Time.timeScale = 0.1f — замедление времени на этапе теста поможет точно отследить момент ошибки.
- Colliders без Rigidbody — частая причина «не работающих» столкновений.
Интеграция UI и системы прогресса
Пользовательский интерфейс в мобильной игре — не просто надстройка, а активный участник игрового цикла. HUD-индикаторы, менюшки, пауза, всплывающие окна после проигрыша — всё это требует внимания не меньше, чем механика. Ошибки в UI кажутся «визуальными», но именно они чаще всего приводят к плохому опыту: нечёткий счёт, неактивная кнопка, неудобное меню. Здесь разберём, как построить UI-часть игры и подключить систему сохранения прогресса.
Конструкция стандартного интерфейса
- HUD — во время игры показывает очки, здоровье, время, бустеры и т. д.
- Pause Menu — вызывается кнопкой, содержит «продолжить», «выйти», «перезапустить»
- Game Over Screen — появляется по проигрышу, сообщает результат, предлагает начать заново
- Main Menu — стартовая сцена с кнопками «Играть», «Настройки», «Выход»
Каждая из этих частей оформляется как Canvas-панель с своими элементами. Для смены UI на сцене используйте активацию/деактивацию GameObject’ов, а не загрузку новых сцен — это быстрее и стабильнее.
Пример: добавим очки и логику HUD
- Добавьте на Canvas Text (или TextMeshPro Text) и назовите
ScoreText - Создайте
ScoreManager.cs:
using UnityEngine;
using UnityEngine.UI;
public class ScoreManager : MonoBehaviour
{
public Text scoreText;
private int score = 0;
public void AddPoint()
{
score++;
UpdateUI();
}
void UpdateUI()
{
scoreText.text = "Очки: " + score.ToString();
}
}
Вызывайте AddPoint() каждый раз, когда игрок проходит препятствие или выживает определённое время. UI всегда отражает текущее состояние логики, не хранит данные сам.
Управление паузой и выходом
При нажатии на кнопку «Пауза» вы можете остановить время в игре через:
public void PauseGame()
{
Time.timeScale = 0f;
pauseMenu.SetActive(true);
}
И аналогично:
public void ResumeGame()
{
Time.timeScale = 1f;
pauseMenu.SetActive(false);
}
Time.timeScale = 0 останавливает и физику, и анимации. Не забывайте включать/отключать UI-элементы отдельно.
Сохранение прогресса
Существует несколько способов сохрани́ть данные между сессиями:
- PlayerPrefs — простой способ сохранить пары «ключ-значение», подходит для очков, настроек
- JSON-файлы — для сложных структур (множество уровней, настройки игрока)
- Serializable ScriptableObjects — продвинутый вариант, удобно использовать при конфигурировании игровых данных
Пример: сохранение наибольшего результата через PlayerPrefs
void SaveHighScore(int score)
{
if (score > PlayerPrefs.GetInt("HighScore", 0))
{
PlayerPrefs.SetInt("HighScore", score);
PlayerPrefs.Save();
}
}
int GetHighScore()
{
return PlayerPrefs.GetInt("HighScore", 0);
}
PlayerPrefs — синхронны, работают быстро, но не подходят для хранения текстур или сложных массивов. Для сериализации прогресса уровней полезнее будет сохранение в JSON-файл на устройство.
Частые ошибки UI-разработки в Unity
- Залипание кнопок — часто возникает, если вам не хватает EventSystem на сцене
- Pixel Perfect элементы — иногда кнопки выглядят мыльно или смещаются — проверьте Canvas Scaler и используйте Sprite PPU = 100
- Игнорирование мультитача — тап-контролы конфликтуют, если камера обрабатывает одно, а UI — другое
- Невидимые элементы — проверьте Z-координаты и SortingLayer у Canvas и объектов, особенно в Mixed UI (2D+3D)
Чем раньше обложите интерфейс через систему менеджеров, тем проще будет дальше внедрять новые экраны, улучшать читаемость HUD и добавлять работу с облаком или рекламой.
Оптимизация и тестирование под мобильные устройства
Качественная мобильная игра должна запускаться и плавно работать не только на флагманах. Более 60% Android-устройств, используемых в СНГ и Азии, не имеют мощного GPU, а FPS ниже 30 сразу выражается в плохих оценках и оттоке игроков. Здесь — подходы к оптимизации, профилировке и тестированию, которые позволяют выжать максимум.
Ресурсоёмкие элементы: на что обратить внимание
- Texture Atlas — объединяйте спрайты в атласы, снижая draw call’ы
- UI batching — используйте draw order в Canvas для группирования
- Collider complexity — избегайте составных физических фигур и mesh-коллайдеров на мобилках
- Animator Overhead — сложные State Machine могут тормозить сцену
Совет: используйте Sprite Packer
Соберите все используемые элементы в Sprite Atlas — стандартный инструмент Unity сделает это автоматически. Включается в Project Settings → Sprite Packer → Always Enabled. Эффект — меньше переключений текстур, стабильнее FPS.
Профилировка производительности
Unity Profiler даёт полную картину по потреблению процессора, памяти и загрузке GPU. Откройте Window → Analysis → Profiler и найдите узкие места. Часто именно UI вызывает больше затрат, чем визуализация объектов.
Что отслеживать:
- CPU Usage — должно быть не выше 20–30 мс на кадр
- Garbage Collection spikes — означает повторяющиеся аллокации объектов
- SetPass Calls — более 100–200 вызовов на сцене говорят о переиспользуемых материалах без батчинга
Общие ориентиры по FPS и производительности
- Цель FPS: не менее 30 на любом железе, 60 на современных устройствах
- Размер сборки: желательно < 100 МБ для Android (с .aab форматами даже меньше)
- Память: менее 150 МБ RAM при простых сценах
Где и как тестировать
- Android: real device first — эмуляторы не отражают поведение реальных касаний, камеры и реального FPS
- TestFlight для iOS — отлично подходит для закрытых тестов и SOFT-launch release
- Firebase Test Lab — облачное тестирование на десятках устройств параллельно
Кейс: на чём чаще всего «падает» игра на Android
- Отсутствующий AndroidManifest.xml или неверный Bundle ID
- Неверно указанный Target API — Play Store требует минимальный API 31+
- Неправильно настроенные Permissions (например, чтение/запись, доступ к сети)
- Перегрузка UI — на дешёвых устройствах интерфейс лагает, особенно при переходе между сценами
Оптимизация — это процесс с постоянной итерацией. Соберите билд, потестируйте, замерьте профилировку, внесите изменения. И так — пока результат не будет стабильно воспроизводим на ключевых устройствах аудитории.
