Главная

Unity 2D туториал для новичков: создаём игру — космическую стрелялку

Добро пожаловать в пошаговый туториал по Unity 2D для новичков! Здесь мы вместе создадим простую, но захватывающую игру — космическую стрелялку. Ты научишься управлять кораблём, стрелять по врагам и использовать встроенную физику 2D в Unity.

Этот урок не требует никакого опыта — всё рассчитано на полных новичков. Просто установи Unity 6.0 LTS (или любую современную версию с поддержкой 2D) и следуй нашим шагам.

Мы пойдём спокойно и без спешки: каждый шаг подробно описан, с пояснениями и примерами. Если ты только начинаешь изучать создание игр на Unity — этот туториал именно для тебя.

Шаг 1. Создание проекта

Начнём с создания нового проекта Unity 2D, выбрав шаблон 2D (Built-in Core). Это даст нам чистую сцену с готовой поддержкой спрайтов, коллайдеров и встроенной 2D-физики.

💡Подсказка: Назови проект SpaceShooter или придумай что-нибудь весёлое — имя на твой вкус.

Шаг 2. Импорт спрайтового листа

Давай перенесём нашу графику в Unity.

Скачай изображение space-sprites.png — в нём есть всё нужное: враги, корабль игрока, снаряды и другое.

Превью спрайтового листа для космической игры
Нажми на изображение, чтобы скачать его.

Открой проект Unity и импортируй файл:

После импорта выбери space-sprites.png в окне Assets. В панели Inspector проверь:

💡Подсказка: “Multiple” означает, что в изображении несколько спрайтов — например, персонажи, снаряды, объекты и т.д.

Unity должен автоматически нарезать изображение при импорте. Если этого не произошло, нажми Open Sprite Editor, затем Slice с выбранным Type: Automatic. Потом нажми Apply.

💡Подсказка: Если автоматическая нарезка не сработает, можно использовать режим по сетке или настроить вручную. Главное — не забудь нажать Apply перед выходом из редактора.

Интерфейс Unity с импортированными и нарезанными спрайтами
Спрайты нарезаны автоматически и теперь отображаются как отдельные ресурсы. При необходимости можно вручную открыть Sprite Editor и настроить нарезку.

Шаг 3. Создание и движение корабля игрока

Построим корабль, которым будем управлять. В этой игре мы не будем использовать клавиатуру — только мышь. Корабль должен лететь туда, куда мы кликаем.

Начни с того, что перетащи синий спрайт корабля в сцену. Unity создаст новый объект. Переименуй его в Player и задай тег Player.

Настрой размеры корабля с помощью Rect Tool прямо в сцене или измени значения Scale в Inspector, чтобы он выглядел так, как тебе нужно.

Теперь добавим физику. С выделенным объектом Player нажми Add Component и добавь:

В настройках Rigidbody 2D:

Затем создай новый скрипт PlayerMove и прикрепи его к объекту Player.

Подсказка: Для этого кликни правой кнопкой в папке AssetsCreate → C# Script, задай имя PlayerMove, а потом дважды кликни по скрипту, чтобы открыть его в Visual Studio или другом редакторе.

В этом скрипте мы определяем точку, куда кликнул игрок мышью, переводим её из экранных координат в мировые (координаты сцены), а затем направляем корабль к этой точке. Всё просто — он всегда летит туда, куда ты укажешь кликом.


using UnityEngine;

public class PlayerMove : MonoBehaviour
{
    // Точка, куда должен лететь корабль (куда кликнул игрок)
    Vector3 clickPos;

    // Вектор направления движения к цели
    Vector3 move;

    // Скорость движения корабля
    public float speed = 1f;

    // Ссылка на Rigidbody2D
    Rigidbody2D rb;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        // При старте игры ставим цель на текущую позицию,
        // чтобы корабль сразу никуда не полетел
        clickPos = transform.position;
    }

    void Update()
    {
        // Каждый кадр проверяем: если нажата левая кнопка мыши,
        // обновляем точку, куда должен лететь корабль
        if (Input.GetMouseButton(0))
        {
            // Переводим позицию мыши из экранных координат в мировые
            clickPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        }

        // Вычисляем направление от текущей позиции к точке назначения
        move = clickPos - transform.position;
    }

    void FixedUpdate()
    {
        // Каждый кадр физики задаём скорость, чтобы лететь к цели
        rb.linearVelocity = new Vector2(move.x, move.y) * speed;
    }
}

Сохрани скрипт и вернись в Unity. В Inspector задай Speed равным 1. Нажми Play и проверь — корабль должен двигаться к точке клика.

💡Подсказка: Положение мыши даётся в экранных координатах — в пикселях. Чтобы использовать его в сцене, преобразуй с помощью Camera.ScreenToWorldPoint. Возвращается точка в мире, но Z-координата будет совпадать с Z-камеры. В 2D это не критично — нас интересуют только X и Y.

Объект Player с Rigidbody2D, Circle Collider и скриптом PlayerMove
Корабль настроен с физикой и скриптом движения. Теперь он плавно летит за кликами мыши.

Шаг 4. Добавление лазера

Теперь дадим нашему кораблю возможность стрелять. Добавим лазер.

Перетащи оранжевый спрайт лазера в сцену. Unity создаст новый объект. Назови его Laser. В Inspector задай Order in Layer равным -10, чтобы он был позади корабля. При необходимости подгони размер — пусть выглядит аккуратно.

Добавь к объекту Laser следующие компоненты и настройки:

Теперь создай новый скрипт MonoBehaviour с именем LaserShot. Этот скрипт будет толкать лазер вверх сразу после создания и удалять его, когда он выйдет за границы экрана.


using UnityEngine;

public class LaserShot : MonoBehaviour
{
    // Ссылка на Rigidbody2D для применения силы
    Rigidbody2D rb;

    // Сила, с которой лазер полетит вверх
    public float force = 5f;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        
        // Создаём вектор, направленный вверх (по Y), с заданной силой
        Vector3 direction = new Vector3(0, force, 0);

        // Придаём лазеру мгновенный импульс в этом направлении
        rb.AddForce(direction, ForceMode2D.Impulse);
    }

    void OnBecameInvisible()
    {
        // Когда лазер выходит за границы камеры, уничтожаем его
        Destroy(gameObject);
    }
}

Прикрепи скрипт к объекту Laser и задай значение Force, например 5.

Затем перетащи объект Laser в окно Assets, чтобы создать префаб. Unity сохранит его автоматически. Теперь можно удалить лазер из сцены — позже мы будем создавать его скриптом.

Объект Laser в Unity с компонентами и сохранённым префабом
Лазер готов — у него есть физика, скрипт движения, и он сохранён как префаб.

Шаг 5. Добавим стрельбу для игрока

Лазер уже умеет летать — теперь сделаем так, чтобы корабль мог его запускать.

Мы создадим новый скрипт, который будет порождать лазер при нажатии правой кнопки мыши. Чтобы избежать слишком частой стрельбы, мы добавим короткую задержку между выстрелами с помощью корутины.

Создай новый скрипт MonoBehaviour с именем PlayerShoot. Он будет выглядеть так:


using UnityEngine;
using System.Collections;

public class PlayerShoot : MonoBehaviour
{
    // Префаб лазера, который будем создавать при выстреле
    public GameObject laser;

    // Задержка между выстрелами (перезарядка)
    public float delayTime = 0.5f;

    // Флаг: можно ли сейчас стрелять
    bool canShoot = true;

    void Update()
    {
        // Каждый кадр проверяем: если нажата правая кнопка мыши
        // и игрок может стрелять (перезарядка прошла)
        if (canShoot && Input.GetMouseButton(1))
        {
            // Запрещаем стрелять до конца перезарядки
            canShoot = false;

            // Создаём лазер (клон префаба) на позиции игрока
            Instantiate(laser, transform.position, transform.rotation);

            // Запускаем таймер перезарядки
            StartCoroutine(NoFire());
        }
    }

    // Корутина — ждёт delayTime секунд и снова разрешает стрелять
    IEnumerator NoFire()
    {
        yield return new WaitForSeconds(delayTime);
        canShoot = true;
    }
}

Прикрепи скрипт PlayerShoot к объекту игрока. Перетащи префаб Laser в поле Laser в инспекторе. Установи Delay Time в 0.5.

Нажми Play и проверь — теперь при правом клике корабль должен стрелять лазером!

Unity: скрипт PlayerShoot с префабом лазера и временем задержки
Скрипт PlayerShoot настроен — у него есть префаб лазера и задержка между выстрелами.

Шаг 6. Добавим враждебные мины

Теперь немного опасности. Мы добавим маленькие вражеские мины, которые будут плавно двигаться вниз к игроку.

Перетащи спрайт мины в сцену. Unity создаст новый объект. Переименуй его в Mine. Установи Order in Layer на -5 (между кораблём и лазером). При необходимости подгони размер.

Добавь к мине следующие компоненты и настройки:

Создай новый тег Enemy и присвой его мине.

Теперь создай новый MonoBehaviour скрипт с именем MineMove. Он будет двигать мину вниз, уничтожать её при выходе за экран и перезапускать сцену, если она столкнётся с игроком.


using UnityEngine;
using System.Collections;
// Эта библиотека нужна для управления сценами (перезагрузки)
using UnityEngine.SceneManagement;

public class MineMove : MonoBehaviour
{
    // Скорость движения мины
    public float speed = 1f;
    Rigidbody2D rb;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        // Создаём вектор, направленный вниз (по Y)
        Vector3 move = new Vector3(0, -1, 0);
        // Задаём линейную скорость Rigidbody, чтобы мина полетела вниз
        rb.linearVelocity = move * speed;
    }

    void OnBecameInvisible()
    {
        // Удаляем мину, если она вышла за пределы экрана
        Destroy(gameObject);
    }

    void OnCollisionEnter2D(Collision2D collision)
    {
        // Проверяем: если мина столкнулась с объектом, у которого тег "Player"
        if (collision.gameObject.tag == "Player")
        {
            // Перезагружаем текущую сцену заново
            SceneManager.LoadScene(SceneManager.GetActiveScene().name);
        }
    }
}

Прикрепи этот скрипт к объекту Mine. Задай Speed равной 1. Затем перетащи мину в окно Assets, чтобы создать префаб. После этого можешь удалить её из сцены — позже мы будем создавать её скриптом.

Префаб мины с физикой и скриптом движения
Префаб враждебной мины готов — с физикой, тегом и логикой движения.

Шаг 7. Автоматическое появление мин

Давайте автоматизируем волны врагов. Мы настроим спавнер, который будет создавать новые мины в случайных позициях.

Зайди в GameObject → Create Empty. Unity создаст пустой объект. Назови его MineSpawner. Можно задать ему кастомную иконку, чтобы его было проще найти в окне сцены.

Перемести MineSpawner в левый верхний угол видимой части экрана. Убедись, что его Z-позиция равна 0 (так как это 2D-игра).

С выделенным MineSpawner нажми Ctrl + D (или правая кнопка → Duplicate). Назови новый объект RightPosition и сделай его дочерним элементом MineSpawner. Перемести его в правый верхний угол экрана. Z-позицию тоже поставь на 0.

Создай новый MonoBehaviour скрипт с именем ObjectSpawner. Он будет выбирать случайную X-позицию между двумя точками и спавнить там мину с задержкой.


using UnityEngine;
using System.Collections;

public class ObjectSpawner : MonoBehaviour
{
  //позиция правой точки спавна
    public Transform RightPosition;
    //период спавна
    public float spawnDelay = 5f;
    //префаб для спавна
    public GameObject Item;

    void Start()
    {
      //периодичный запуск функции спавна
        InvokeRepeating("Spawn", spawnDelay, spawnDelay);
    }

    void Spawn()
    {
      //находим случайную точку между границами спавна
        Vector3 spawnPos = new Vector3(
            Random.Range(transform.position.x, RightPosition.position.x),
            transform.position.y,
            0);
//спавним объект (мину)
        Instantiate(Item, spawnPos, transform.rotation);
    }
}

Прикрепи скрипт к объекту MineSpawner. Перетащи RightPosition в поле Right Position, а префаб Mine — в поле Item. Установи Spawn Delay на 5.

Нажми Play — теперь мины будут появляться сверху в случайных местах.

Объект MineSpawner с прикреплённым скриптом и полями для префабов
MineSpawner теперь создаёт мины между двумя точками по верхнему краю экрана.

Шаг 8. Здоровье и урон

Сейчас лазеры просто пролетают сквозь мины — никакой реакции. Давай это исправим: добавим минам очки здоровья и сделаем так, чтобы лазеры наносили урон.

Создай новый MonoBehaviour-скрипт с именем HpController. Он будет хранить значение здоровья и удалять объект, когда оно станет нулевым.


using UnityEngine;

public class HpController : MonoBehaviour
{
    // Количество очков здоровья (HP)
    public int hp = 3;

    // Метод, который уменьшает здоровье на величину полученного урона
    void MakeDamage(int damage)
    {
        // Вычитаем полученный урон из текущего количества здоровья
        hp -= damage;

        // Если здоровье упало до нуля или ниже — уничтожаем объект
        if (hp <= 0)
        {
            Destroy(gameObject);
        }
    }
}

Выбери префаб Mine в окне Assets и добавь к нему скрипт HpController. Установи hp равным 3.

Теперь открой скрипт LaserShot. Мы добавим проверку столкновений и передадим урон врагу.


using UnityEngine;

public class LaserShot : MonoBehaviour
{
    // Ссылка на Rigidbody2D для применения силы
    Rigidbody2D rb;

    // Сила, с которой лазер будет лететь вверх
    public float force = 10f;

    // Количество урона, которое наносит лазер врагам
    public int damage = 1;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        // Создаём вектор, направленный вверх, с заданной силой
        Vector3 direction = new Vector3(0, force, 0);

        // Применяем к лазеру мгновенный импульс, чтобы он полетел
        rb.AddForce(direction, ForceMode2D.Impulse);
    }

    void OnBecameInvisible()
    {
        // Уничтожаем лазер, когда он выходит за пределы экрана
        Destroy(gameObject);
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        // Проверяем, столкнулся ли лазер с объектом, у которого тег "Enemy"
        if (other.gameObject.tag == "Enemy")
        {
            // Отправляем врагу сообщение "MakeDamage", передавая ему величину урона.
            // Если у объекта нет такого метода — ошибки не будет.
            other.gameObject.SendMessage("MakeDamage", damage, SendMessageOptions.DontRequireReceiver);

            // Уничтожаем лазер после попадания
            Destroy(gameObject);
        }
    }
}

Выбери префаб Laser и в Inspector установи значение Damage равным 1.

Нажми Play и проверь — теперь минам потребуется три попадания, чтобы быть уничтоженными.

Префаб мины с HpController и логикой урона
Префаб мины теперь имеет здоровье и может быть уничтожен лазером.

Шаг 9. Вражеский корабль и его ракета

Добавим врага, который сможет стрелять в ответ.

Перетащи спрайт вражеского корабля в сцену. Unity автоматически создаст новый объект. Переименуй его в Enemy-1. Поменяй его тег на Enemy. Установи Order in Layer на -5, чтобы враг отображался над лазерами. При необходимости подгони размер.

Добавь к объекту следующие компоненты и настройки:

Теперь добавь скрипт HpController на вражеский корабль и установи в нём HP в 1. Также добавь на этот объект скрипт MineMove и задай для него speed 1 (или на своё усмотрение), чтобы тарелка спокойно двигалась вниз.

Затем перетащи Enemy-1 в окно Assets, чтобы создать новый префаб врага. После создания префаба можешь удалить Enemy-1 из сцены — он сохранится в проекте как префаб.

Префаб врага с Rigidbody 2D, Circle Collider 2D
Префаб врага с Rigidbody 2D, Circle Collider 2D и скриптом HpController, MineMove.

Теперь добавим врагу ракету. Перетащи спрайт ракеты в сцену и назови объект Rocket. Установи Order in Layer равным -10. Добавь Box Collider 2D и включи Is Trigger. Добавь Rigidbody2D со значениями Gravity Scale = 0 и Interpolate = Interpolate.

Создай новый MonoBehaviour скрипт с именем EnemyBullet. Он будет делать следующее: после спавна ракета попробует найти игрока в сцене по тегу Player. Если игрок найден, ракета повернётся в его сторону и полетит к нему. Если игрока нет — ракета удалится.


using UnityEngine;

public class EnemyBullet : MonoBehaviour
{
    // Ссылка на игрока
    GameObject player;

    // Ссылка на Rigidbody2D для применения силы
    Rigidbody2D rb;

    // Сила импульса, с которой ракета полетит
    public float force = 3f;

    // Урон, который ракета нанесёт при попадании
    public int damage = 1;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        // Находим игрока в сцене по тегу "Player"
        player = GameObject.FindWithTag("Player");

        if (player != null)
        {
            // Вычисляем направление от ракеты до игрока
            Vector3 dir = player.transform.position - transform.position;

            // Поворачиваем ракету в сторону игрока
            transform.up = dir;

            // Применяем импульс в направлении "вверх" ракеты (т.е. туда, куда она повернута)
            rb.AddRelativeForce(transform.up * force, ForceMode2D.Impulse);
        }
        else
        {
            // Если игрока нет на сцене — удаляем ракету
            Destroy(gameObject);
        }
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        // Проверяем, столкнулась ли ракета с игроком
        if (other.gameObject.tag == "Player")
        {
            // Отправляем игроку сообщение о получении урона
            other.gameObject.SendMessage("MakeDamage", damage, SendMessageOptions.DontRequireReceiver);

            // Уничтожаем ракету после попадания
            Destroy(gameObject);
        }
    }

    void OnBecameInvisible()
    {
        // Удаляем ракету, если она вышла за пределы камеры
        Destroy(gameObject);
    }
}

Прикрепи скрипт EnemyBullet к объекту Rocket. Установи Force равным 3, а Damage1. Затем создай префаб, перетащив ракету в окно Assets, и удали её из сцены.

Префаб ракеты с EnemyBullet и компонентами физики
Префаб ракеты врага готов — она находит игрока, поворачивается и летит вперёд.

Шаг 10. Заставим врага стрелять

Пора дать вражескому кораблю огневую мощь. Мы добавим скрипт стрельбы, который будет периодически создавать ракету, а остальное ракета сделает сама.

Создай новый MonoBehaviour скрипт и назови его EnemyShoot. Это простой скрипт, который периодически будет спавнить ракеты, если в сцене есть игрок.


using UnityEngine;
using System.Collections;

public class EnemyShoot : MonoBehaviour
{
    // Префаб ракеты, которую будем создавать
    public GameObject bullet;

    // Задержка между выстрелами (секунды)
    public float fireDelay = 2f;

    // Ссылка на игрока в сцене
    GameObject player;

    // Флаг: можно ли сейчас стрелять
    bool canShoot = true;

    void Start()
    {
        // Ищем игрока в сцене по тегу "Player"
        player = GameObject.FindWithTag("Player");
    }

    void Update()
    {
        // Если можно стрелять и игрок найден
        if (canShoot && player != null)
        {
            // Запрещаем стрелять до следующей задержки
            canShoot = false;

            // Создаём ракету в позиции врага
            Instantiate(bullet, transform.position, Quaternion.identity);

            // Запускаем корутину, чтобы подождать перед следующим выстрелом
            StartCoroutine(firePause());
        }
    }

    IEnumerator firePause()
    {
        // Ждём fireDelay секунд
        yield return new WaitForSeconds(fireDelay);

        // Снова разрешаем стрелять
        canShoot = true;
    }
}

Выбери префаб Enemy-1 в окне Assets. Добавь к нему скрипт EnemyShoot. В поле Bullet перетащи префаб Rocket. Установи Fire Delay равным 2.

Префаб Enemy-1 со скриптом EnemyShoot и привязанной ракетой
Префаб Enemy-1 теперь вооружён и готов стрелять ракетами по игроку.

Шаг 11. Появление врагов вместе с минами

Наш префаб Enemy-1 готов. Теперь сделаем так, чтобы он появлялся в сцене, как и мины. Вместо создания второго спавнера мы улучшим уже существующий, добавив возможность выбирать объект случайным образом из нескольких.

Открой скрипт ObjectSpawner и обнови его, чтобы он использовал массив префабов:


using UnityEngine;

public class ObjectSpawner : MonoBehaviour
{
    // Правая граница спавна (левая - это сам объект, к которому прикреплен этот скрипт)
    public Transform RightPosition;

    // Задержка между спавнами (секунды)
    public float spawnDelay;

    // Массив префабов, которые будем случайно выбирать для спавна
    public GameObject[] Item;

    void Start()
    {
        // Запускаем функцию Spawn периодически через заданную задержку
        InvokeRepeating("Spawn", spawnDelay, spawnDelay);
    }

    void Spawn()
    {
        // Вычисляем случайную точку между нашим объектом и RightPosition по оси X
        Vector3 spawnPos = new Vector3(
            Random.Range(transform.position.x, RightPosition.position.x),
            transform.position.y,
            0
        );

        // Случайно выбираем один префаб из массива Item
        int i = Random.Range(0, Item.Length);

        // Создаём выбранный объект в вычисленной позиции
        Instantiate(Item[i], spawnPos, transform.rotation);
    }
}

В объекте MineSpawner (в сцене) посмотри на обновлённый список Item. Добавь в него префабы Mine и Enemy-1. Unity сам подберёт нужный размер массива.

Объект MineSpawner со списком Mine и Enemy-1
Теперь спавнер выбирает случайно между префабами Mine и Enemy-1. Да начнётся хаос.

Шаг 12. Создание индикатора здоровья

У игрока до сих пор нет видимого здоровья. Давай добавим простую панель UI, чтобы отображать текущий уровень жизни на экране. Мы сделаем горизонтальный индикатор здоровья с помощью встроенной системы UI в Unity.

Зайди в GameObject → UI → Image. Unity создаст Canvas с объектом Image внутри. Переименуй Image в HealthBar.

Выдели Canvas. В Inspector, в компоненте Canvas Scaler, установи: UI Scale Mode на Scale With Screen Size.

Дважды кликни по Canvas в Hierarchy — сцена отдалится, и ты увидишь область UI. Выдели HealthBar и с помощью Rect Tool растяни его в форму полосы. Размести там, где удобно по компоновке.

С выделенным HealthBar:

Примечание: Fill Method и Origin могут установиться автоматически при выборе Filled. Позже можно поэкспериментировать, но пока оставь как есть.

Canvas с UI-элементом HealthBar в виде горизонтальной полосы
HealthBar теперь часть Canvas. В следующем шаге мы будем управлять его заполнением.

Шаг 13. Управление здоровьем игрока

Теперь давайте свяжем индикатор здоровья с игровым процессом. Мы напишем скрипт, который будет отслеживать получаемый игроком урон и обновлять панель здоровья. У компонента Image на объекте HealthBar есть свойство fillAmount, которое управляет степенью заполненности спрайта. Вычисляя процент оставшегося здоровья, мы будем изменять fillAmount, чтобы визуально показывать текущее количество HP на нашем индикаторе.

Создай новый MonoBehaviour-скрипт с именем PlayerHp:


using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class PlayerHp : MonoBehaviour
{
    // Ссылка на объект полоски здоровья (UI Image)
    public GameObject HealthBar;
    // Ссылка на компонент Image для изменения fillAmount
    Image img;

    // Текущее здоровье
    public int hp;
    // Максимальное здоровье (нужно для нормализации полоски)
    float maxHp;

    void Start()
    {
        // Получаем Image с объекта HealthBar
        img = HealthBar.GetComponent<Image>();
        // Сохраняем максимальное здоровье
        maxHp = hp;
        // Устанавливаем начальное заполнение полоски
        img.fillAmount = hp / maxHp;
    }

    // Метод для получения урона
    void MakeDamage(int damage)
    {
        // Вычитаем урон из здоровья
        hp -= damage;

        // Если здоровье закончилось — перезапускаем сцену
        if (hp <= 0)
        {
            SceneManager.LoadScene(SceneManager.GetActiveScene().name);
        }

        // Обновляем полоску здоровья
        img.fillAmount = hp / maxHp;
    }
}

Перейди в сцену и выбери объект Player. Добавь к нему скрипт PlayerHp. Перетащи HealthBar (из Canvas) в поле Health Bar. Установи значение HP равным 10.

Объект Player со скриптом PlayerHp и подключённой HealthBar
У игрока теперь есть здоровье, и он будет уничтожен, если оно закончится.

Шаг 14. Установка фонового цвета

Начнём с того, что превратим фон сцены в глубокий космос. Выдели Main Camera в Hierarchy. В Inspector, в разделе Camera, установи цвет Background в black.

Шаг 15. Добавим движущиеся звёзды с помощью Particle System

Чтобы создать эффект космоса, мы используем встроенную систему частиц Unity — она будет имитировать движущиеся звёзды.

  1. Открой GameObject → Effects → Particle System.
  2. Переименуй новый объект в Stars.
  3. Установи Z Position в 10 и X Rotation в 90.
  4. Подними его вверх — за пределы видимой области камеры.
  5. В настройках Particle System:
    • Включи Prewarm.
    • Настрой Start Lifetime так, чтобы частицы летели через весь экран.
    • Установи Start Speed по вкусу.
    • Start Size0.2 (или на свой вкус).
  6. В модуле Shape:
    • Shape = Box
    • X = 15 — чтобы звёзды покрывали широкую область.
  7. В модуле Renderer:
    • Order in Layer = -100 — чтобы звёзды были позади всех объектов.
Система частиц Stars, размещённая над сценой с заданными параметрами
Теперь звёзды мягко дрейфуют на фоне сцены — галактика ожила.

Шаг 16. Добавим звук выстрела

Давайте дадим вражеской ракете полноценный звук выстрела. Когда ракета появляется, мы проиграем короткий звуковой эффект с помощью встроенной аудиосистемы Unity.

Ты можешь скачать звуки, используемые в этом туториале, здесь:

Импортируй скачанные аудиофайлы в Unity.

Для проигрывания звука в скрипте EnemyBullet мы используем метод PlayClipAtPoint.

С его помощью воспроизводится нужный аудиофайл в момент запуска ракеты. Это создаёт временный звуковой объект в сцене, который сразу проигрывает звук и затем автоматически исчезает.

Вот полный обновлённый скрипт EnemyBullet с поддержкой звука:


using UnityEngine;

public class EnemyBullet : MonoBehaviour
{
    // Ссылка на игрока (ищем по тегу "Player")
    GameObject player;

    // Ссылка на Rigidbody2D для физического движения
    Rigidbody2D rb;

    // Сила, с которой летит пуля
    public float force = 3f;

    // Урон, который нанесёт пуля
    public int damage = 1;

    // Звук выстрела
    public AudioClip BulletSound;

    void Start()
    {
        // Получаем Rigidbody2D
        rb = GetComponent<Rigidbody2D>();

        // Находим игрока по тегу
        player = GameObject.FindWithTag("Player");

        // Если игрок найден
        if (player != null)
        {
            // Вычисляем направление к игроку
            Vector3 dir = player.transform.position - transform.position;

            // Поворачиваем пулю в эту сторону
            transform.up = dir;

            // Задаём силу, чтобы пуля полетела в эту сторону
            rb.AddRelativeForce(transform.up * force, ForceMode2D.Impulse);

            // Проигрываем звук выстрела в позиции пули
            AudioSource.PlayClipAtPoint(BulletSound, transform.position);
        }
        else
        {
            // Если игрок не найден — уничтожаем пулю
            Destroy(gameObject);
        }
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        // Если пуля попала в игрока
        if (other.gameObject.tag == "Player")
        {
            // Отправляем игроку сообщение о получении урона
            other.gameObject.SendMessage("MakeDamage", damage, SendMessageOptions.DontRequireReceiver);

            // Уничтожаем пулю
            Destroy(gameObject);
        }
    }

    void OnBecameInvisible()
    {
        // Уничтожаем пулю, если она вышла за пределы экрана
        Destroy(gameObject);
    }
}

Теперь выбери префаб Rocket. Присвой звук LaserSound полю Bullet Sound в скрипте EnemyBullet.

💡 Ты можешь заменить этот звук на любой другой, импортировав свой файл .wav и назначив его в поле AudioClip.

Префаб ракеты с прикреплённым звуком выстрела
Теперь ракета издаёт звук при появлении — сражение становится ещё живее.

Шаг 17. Добавим звук стрельбы для лазера игрока

Как и у вражеских ракет, мы хотим добавить звук выстрела для лазера игрока. Открой скрипт LaserShot и обнови его следующим образом:


using UnityEngine;

public class LaserShot : MonoBehaviour
{
    // Ссылка на Rigidbody2D, чтобы управлять физикой
    Rigidbody2D rb;

    // Сила импульса, с которой лазер полетит вверх
    public float force = 10f;

    // Сколько урона наносит лазер
    public int damage = 1;

    // Аудиоклип для звука выстрела
    public AudioClip LaserSound;

    void Start()
    {
        // Получаем Rigidbody2D на этом объекте
        rb = GetComponent<Rigidbody2D>();

        // Создаём вектор направления полёта (по Y вверх)
        Vector3 direction = new Vector3(0, force, 0);

        // Придаём импульс объекту в этом направлении
        rb.AddForce(direction, ForceMode2D.Impulse);

        // Проигрываем звук выстрела в точке создания лазера
        AudioSource.PlayClipAtPoint(LaserSound, transform.position);
    }

    void OnBecameInvisible()
    {
        // Уничтожаем лазер, когда он выходит за пределы камеры
        Destroy(gameObject);
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        // Если столкнулись с объектом, который имеет тег "Enemy"
        if (other.gameObject.tag == "Enemy")
        {
            // Отправляем врагу сообщение о получении урона
            other.gameObject.SendMessage("MakeDamage", damage, SendMessageOptions.DontRequireReceiver);

            // Уничтожаем лазер после столкновения
            Destroy(gameObject);
        }
    }
}

После обновления скрипта выбери префаб Laser в окне Assets и назначь аудиофайл LaserSound.wav в поле Laser Sound.

💡 Если ты хочешь использовать свой звук вместо предложенного — просто перетащи свой файл .wav в папку Assets/sound и укажи его в инспекторе.

Префаб лазера с добавленным звуковым эффектом
Префаб лазера с добавленным звуковым эффектом

Шаг 18. Добавим звук взрыва при уничтожении объектов

Когда враги и мины уничтожаются, пусть воспроизводится короткий звук взрыва. Для этого немного расширим скрипт HpController: добавим звуковое поле и проиграем звук, когда здоровье обнуляется.


using UnityEngine;

public class HpController : MonoBehaviour
{
    // Очки здоровья объекта
    public int hp = 3;

    // Звуковой эффект для взрыва
    public AudioClip ExplosionsSound;

    void MakeDamage(int damage)
    {
        // Вычитаем урон из здоровья
        hp -= damage;

        // Если здоровье закончилось
        if (hp <= 0)
        {
            // Проигрываем звук взрыва
            AudioSource.PlayClipAtPoint(ExplosionsSound, transform.position);

            // Уничтожаем объект
            Destroy(gameObject);
        }
    }
}

Выдели префабы Mine и Enemy-1 в окне Assets. В компоненте HpController назначь файл Boom.wav в поле Explosions Sound.

Готово! Теперь каждый раз при уничтожении врага или мины будет проигрываться приятный звуковой эффект.

💡 Можно использовать и собственный звук — просто перетащи свой .wav в папку Assets/sound и назначь его.

Префаб врага с добавленным звуковым эффектом
Префаб врага с добавленным звуковым эффектом

Шаг 19. Эффект взрыва

Добавим визуальный эффект при уничтожении врагов (мин или Enemy-1). Создай новый объект Particle System и назови его KiavoBoom. Установи Position и Rotation в 0. В Inspector задай следующие параметры:

Перейди в модуль Emission, добавь Burst во время 0.0 с количеством 30.
В модуле Shape выбери Shape = Circle и Radius = 0.1.

Включи Color over Lifetime. В редакторе цвета задай финальный Alpha = 0, а начальные и конечные цвета выбери на свой вкус. В модуле Renderer установи Order in Layer = 10 (находится в настройках Renderer).

В разделе Main установи параметр Stop Action в значение Destroy. Это означает, что объект сам удалится после завершения эффекта.

После этого создай из KiavoBoom префаб и можешь удалить его из сцены — он сохранится в проекте для использования при спавне.

Позже ты можешь поэкспериментировать с более яркими эффектами или цветами — а пока это простой и быстрый эффект взрыва.

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

Шаг 20. Создаём взрыв при уничтожении врага

Теперь у нас есть префаб взрыва. Давайте сделаем так, чтобы он появлялся при уничтожении врага (например, мины или Enemy-1). Открой скрипт HpController и измени его так:


using UnityEngine;

public class HpController : MonoBehaviour
{
    // Количество очков здоровья
    public int hp = 3;

    // Префаб эффекта взрыва
    public GameObject Explosion;

    // Звук взрыва
    public AudioClip ExplosionsSound;

    void MakeDamage(int damage)
    {
        // Вычитаем урон из здоровья
        hp -= damage;

        // Если здоровье закончилось
        if (hp <= 0)
        {
            // Проигрываем звук взрыва
            AudioSource.PlayClipAtPoint(ExplosionsSound, transform.position);

            // Создаём эффект взрыва
            Instantiate(Explosion, transform.position, Quaternion.identity);

            // Уничтожаем объект
            Destroy(gameObject);
        }
    }
}

Теперь выбери префабы Mine и Enemy-1. В компоненте HpController назначь префаб взрыва (например, KiavoBoom) в поле Explosion.

Префаб взрыва, добавленный в врагов
Взрыв KiavoBoom теперь подключён в HpController каждого врага. При уничтожении — звук и частицы.

Шаг 21. Что дальше?

Наша игра завершена — в ней есть движение, враги, стрельба, звук и интерфейс. Этот туториал был посвящён созданию простой, но рабочей 2D-космической стрелялки с использованием базовых возможностей Unity.

Конечно, ты можешь продолжать развивать её: добавить анимации, визуальные эффекты, волны врагов, счёт, жизни, меню, босса, фоновую музыку… даже летающих куриц или космический чай ☕🛸

Но наша цель была — показать чистую и понятную основу. И теперь она у тебя есть.

💡 Продолжай экспериментировать, играй, и создавай свою собственную версию!