Главная

Урок 4: 2D платформер — Часть 1

Привет! В этом туториале мы вместе создадим простой 2D платформер на движке Unity. Тебе не нужно быть экспертом — мы всё объясним понятно и пошагово. Мы будем использовать встроенную физику 2D и немного коснёмся анимации (привет, спрайт-листы!). Чтобы пройти урок, тебе понадобятся некоторые ресурсы: изображения, звуки и не только. Скачать архив .zip можно здесь — в нём есть всё, что нужно для старта.

Шаг 1. Настройка земли и игрока

Запусти Unity и создай новый 2D-проект. Сначала мы сделаем основу игры: объект земли и персонажа.

Сначала импортируй largeGround из архива (если нужно — скачать здесь). Распакуй .zip и перетащи largeGround в сцену. Переименуй созданный GameObject в Ground.

Выбери Ground в иерархии. В инспекторе:

Теперь добавим игрока. Импортируй спрайт-лист ratIdle (он тоже в архиве). Unity, скорее всего, автоматически нарежет его. Если нет — сделай так:

Разверни спрайт-лист — теперь в нём должно быть 20 кадров. Перетащи первый кадр в сцену. Переименуй созданный GameObject в Rat.

Выбери объект Rat и сделай следующие настройки:

Сцена в Unity с настроенной землёй и крысой
Сцена с объектами Ground и Rat.

Шаг 2. Движение и прыжки

Пора заставить нашу крыску двигаться! Создадим скрипт, который будет отвечать и за бег, и за прыжки.

В папке Assets кликни правой кнопкой мыши и выбери создание нового C#-скрипта. Назови его PlayerMove. Этот скрипт будет использовать компонент Rigidbody2D для перемещения игрока с помощью встроенной физики Unity. Мы также добавим прыжок, применяя силу вверх по оси Y.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMove : MonoBehaviour
{
    // Какие слои считаются "землёй" (задать в Инспекторе)
    public LayerMask whatIsGround;

    // Точка, по которой проверяется, стоит ли игрок на земле
    public Transform groundCheck;

    // Находится ли игрок сейчас на земле?
    public bool isGrounded;

    // Сила прыжка
    public float jumpForce;

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

    // Ссылка на компонент Rigidbody2D
    Rigidbody2D rb;

    void Start()
    {
        // Получаем компонент Rigidbody2D, прикреплённый к объекту
        rb = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        // Если нажата кнопка прыжка и игрок стоит на земле
        if (Input.GetButtonDown("Jump") && isGrounded)
        {
            // Добавляем силу вверх для прыжка
            rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
            // Запрещаем повторный прыжок — сбросится в FixedUpdate
            isGrounded = false;
        }
    }

    void FixedUpdate()
    {
        // Проверяем, касается ли точка GroundCheck слоя "земля"
        isGrounded = Physics2D.OverlapPoint(groundCheck.position, whatIsGround);

        // Получаем горизонтальный ввод (стрелки или A/D)
        float x = Input.GetAxis("Horizontal");

        // Создаём вектор движения (сохраняем вертикальную скорость)
        Vector3 move = new Vector3(x * speed, rb.linearVelocity.y, 0f);

        // Применяем движение к Rigidbody
        rb.linearVelocity = move;
    }
}

Прикрепи скрипт PlayerMove к объекту Rat. В инспекторе установи Speed на 3 и Jump Force на 5.

Теперь создадим вспомогательный объект для определения земли. Кликни правой кнопкой на Rat в иерархии → Create Empty, переименуй его в GroundCheck и перемести чуть ниже лапок крысы (но вне её коллайдера).

Чтобы прыжки работали, нужно ещё указать, что такое “земля”. Выдели объект Ground и задай ему Layer как Ground. Если слоя с таким названием нет — создай его.

Теперь снова выбери Rat. В компоненте PlayerMove:

💡 Совет: Если слой Ground не отображается в списке, убедись, что ты выделил объект земли и добавил нужный слой.

Нажми Play — теперь крыса должна двигаться влево и вправо (с помощью стрелок или A/D) и прыгать, когда стоит на земле.

Инспектор Unity с настройками PlayerMove и GroundCheck у крысы
Скрипт PlayerMove настроен на объекте Rat.

Шаг 3. Поворачиваемся в нужную сторону

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

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMove : MonoBehaviour
{
    // Какие слои считаются "землёй" (указать в инспекторе)
    public LayerMask whatIsGround;

    // Точка, по которой проверяется, стоит ли игрок на земле
    public Transform groundCheck;

    // Стоит ли игрок сейчас на земле?
    public bool isGrounded;

    // Сила прыжка
    public float jumpForce;

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

    // Ссылка на компонент Rigidbody2D
    Rigidbody2D rb;

    // Указывает, смотрит ли крыса влево (true = влево)
    public bool isLookingLeft;

    void Start()
    {
        // Получаем компонент Rigidbody2D, прикреплённый к объекту
        rb = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        // Если нажата кнопка прыжка и крыса на земле
        if (Input.GetButtonDown("Jump") && isGrounded)
        {
            // Прыгаем вверх с заданной силой
            rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
            // Запрещаем двойной прыжок — флаг сбросится в FixedUpdate
            isGrounded = false;
        }
    }

    void FixedUpdate()
    {
        // Проверка: GroundCheck касается слоя земли?
        isGrounded = Physics2D.OverlapPoint(groundCheck.position, whatIsGround);

        // Получаем ввод по горизонтали (стрелки или A/D)
        float x = Input.GetAxis("Horizontal");

        // Создаём вектор движения (сохраняем вертикальную скорость)
        Vector3 move = new Vector3(x * speed, rb.linearVelocity.y, 0f);

        // Применяем движение
        rb.linearVelocity = move;

        // Если идём влево и ещё не повернуты влево — поворачиваемся
        if (x < 0 && !isLookingLeft)
    TurnTheRat();

        // Если идём вправо, а смотрим влево — тоже поворачиваемся
        if (x > 0 && isLookingLeft)
    TurnTheRat();
    }

    // Поворачивает крысу, инвертируя масштаб по оси X
    void TurnTheRat()
    {
        // Меняем флаг направления
        isLookingLeft = !isLookingLeft;

        // Зеркально отражаем спрайт
        transform.localScale = new Vector3(
            transform.localScale.x * -1,
            transform.localScale.y,
            transform.localScale.z
        );
    }
}

Выдели объект Rat в иерархии. В компоненте PlayerMove поставь галочку Is Looking Left — она должна соответствовать исходному направлению спрайта (если твоя крыса изначально смотрит влево).

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

Шаг 4. Подготавливаем анимацию

Начнём анимировать нашу крысу! Для начала добавим компонент Animator и создадим контроллер.

В иерархии выбери GameObject Rat. В инспекторе нажми Add Component и выбери Animator.

Затем в окне Assets кликни правой кнопкой и создай новый Animator Controller. Назови его RatAnimator.

Теперь присвой контроллер RatAnimator полю Controller в компоненте Animator у объекта Rat.

Компонент Animator и контроллер, назначенные на крысу
Компонент Animator добавлен, контроллер RatAnimator назначен.

Шаг 5. Создание анимации ожидания

Давай оживим крысу с помощью её первой анимации — петли ожидания (idle loop).

Открой окно Animation, если оно ещё не видно. Можно включить его через Window → Animation → Animation и закрепить где тебе удобно (я, например, размещаю его над окном Assets).

Выбери объект Rat в иерархии. В окне Animation нажми Create и сохрани новую анимацию с именем IdleRatAnimation.

Теперь добавим кадры из спрайт-листа. В окне Assets разверни ratIdle. Выдели все 20 кадров: кликни по первому, затем удерживай Shift и кликни по последнему. Перетащи выделенные кадры на временную шкалу (timeline) в окне Animation.

Открой окно Animator (через Window → Animation → Animator), если оно ещё не открыто. Дважды кликни по состоянию IdleRatAnimation — или просто выбери его в Assets.

В панели Inspector убедись, что включён параметр Loop Time (цикличное воспроизведение). Можно также настроить Speed — например, поставить 0.5, чтобы анимация выглядела более плавной.

Настройка IdleRatAnimation в окнах Animator и Animation Unity
Анимация IdleRatAnimation добавлена в Animator и зациклена. Скорость воспроизведения установлена на 0.5 для плавности.

Шаг 6. Анимация бега и переходы

Пора анимировать движение крысы! Давай создадим анимацию бега и настроим переходы между состояниями.

Сначала импортируй спрайт ratRun из архива в папку Assets.

Выдели объект Rat в иерархии. В окне Animation нажми на выпадающий список рядом с IdleRatAnimation и выбери Create New Clip. Назови новую анимацию RunRatAnimation.
(Убедись, что объект Rat выбран в иерархии — иначе Unity не даст добавить новую анимацию.)

В окне Assets разверни ratRun и выдели все 20 кадров: кликни по первому, зажми Shift и кликни по последнему. Перетащи все выделенные кадры в окно Animation, чтобы заполнить временную шкалу.

Открой окно Animator. Если его не видно — включи через Window → Animation → Animator.

По умолчанию, IdleRatAnimation — начальное состояние. Мы создадим параметр типа Float, чтобы управлять переходами между ожиданием и бегом.

Теперь настроим сами переходы:

Переходы между Idle и Run с параметром Speed в Animator
Переходы в Animator и параметр Speed. Не забудь отключить Has Exit Time и задать условия.

Шаг 7. Переключение анимаций через код

Чтобы управлять переходами между анимациями, мы создадим простой скрипт, который будет передавать информацию о движении в Animator. Он будет переключаться между Idle и Run в зависимости от скорости крысы.

В папке Assets создай новый C#-скрипт и назови его PlayerAnim. Затем вставь следующий код:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerAnim : MonoBehaviour
{
    // Ссылка на Animator
    Animator anim;

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

    void Start()
    {
        anim = GetComponent<Animator>();
        rb = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        // Обновляем параметр Speed в Animator (по абсолютному значению горизонтальной скорости)
        anim.SetFloat("Speed", Mathf.Abs(rb.linearVelocity.x));
    }
}

Прикрепи скрипт PlayerAnim к объекту Rat.

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

Шаг 8. Добавляем анимацию прыжка

Давай создадим анимацию прыжка для нашей крысы. У нас нет отдельного спрайта для прыжка, но мы можем повторно использовать ratRun с уменьшенной скоростью — получится эффект прыжка.

Выдели объект Rat в иерархии. В окне Animation нажми на выпадающий список и выбери Create New Clip. Назови новую анимацию JumpRatAnimation.

В Assets разверни спрайт-лист ratRun. Выдели все 20 кадров (первый → Shift → последний), затем перетащи их в таймлайн окна Animation.

Открой окно Animator. Сейчас мы добавим параметр и свяжем его с логикой прыжка.

Настроим переходы следующим образом:

Наконец, выдели состояние JumpRatAnimation и установи Speed на 0.2, чтобы бег выглядел как прыжок.

Окно Animator с анимацией прыжка и настроенными переходами
Анимация JumpRatAnimation добавлена, переходы настроены. Скорость 0.2, параметр isJumping управляет переходами.

Шаг 9. Обнаружение прыжка в коде

Теперь свяжем анимацию прыжка с фактическим состоянием крысы. Для этого мы получим доступ к переменной isGrounded из скрипта PlayerMove. Если крыса не на земле (включая падение), будет запускаться анимация прыжка.

Открой скрипт PlayerAnim и замени содержимое на следующее:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerAnim : MonoBehaviour
{
    // Ссылка на компонент Animator
    Animator anim;

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

    // Ссылка на скрипт PlayerMove (для доступа к isGrounded)
    PlayerMove pm;

    void Start()
    {
        // Получаем компонент Animator с этого объекта
        anim = GetComponent<Animator>();

        // Получаем компонент Rigidbody2D
        rb = GetComponent<Rigidbody2D>();

        // Получаем скрипт PlayerMove
        pm = GetComponent<PlayerMove>();
    }

    void Update()
    {
        // Если крыса стоит на земле
        if (pm.isGrounded)
        {
            // Прыжок завершён
            anim.SetBool("isJumping", false);

            // Обновляем Speed на основе горизонтального движения
            anim.SetFloat("Speed", Mathf.Abs(rb.linearVelocity.x));
        }
        else
        {
            // Во время прыжка или падения скорость ставим в 0
            anim.SetFloat("Speed", 0);

            // Включаем анимацию прыжка
            anim.SetBool("isJumping", true);
        }
    }
}

И всё! Больше ничего настраивать не нужно. Теперь анимация прыжка будет включаться автоматически, как только крыса окажется в воздухе — прыгая вверх или падая вниз.

Шаг 10. Добавляем звуки шагов

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

В папке Assets создай новый C#-скрипт и назови его PlayerSound. Вставь в него следующий код:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerSound : MonoBehaviour
{
    // Аудиоклип со звуком шагов
    public AudioClip footsteps;

    // Публичная функция для воспроизведения звука — вызывается из анимации
    public void FootStepsAudio()
    {
        // Воспроизводим звук в позиции крысы
        AudioSource.PlayClipAtPoint(footsteps, transform.position);
    }
}

Выбери объект Rat в иерархии и добавь к нему скрипт PlayerSound. Затем импортируй звук ratStep из архива и назначь его в поле Footsteps компонента.

Теперь открой окно Animation и выбери RunRatAnimation. Найди подходящий кадр, где происходит шаг, и нажми Add Event на таймлайне. В панели Inspector (справа) укажи имя функции FootStepsAudio().

Событие анимации в RunRatAnimation, вызывающее функцию FootStepsAudio
Событие анимации, вызывающее функцию FootStepsAudio() во время анимации бега.

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

Шаг 11. Копирование платформ и следящая камера

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

Сначала преврати исходный объект земли в префаб. Выдели Ground в иерархии и перетащи его в папку Assets, чтобы создать префаб.

Теперь перетащи этот префаб обратно в сцену несколько раз, чтобы создать дополнительные платформы. Расположи их на разных горизонтальных (и при желании — вертикальных) уровнях, чтобы добавить немного прыжкового вызова.

Затем выбери Main Camera в иерархии и перетащи её внутрь объекта Rat. Теперь камера станет дочерним объектом крысы и будет следовать за ней при движении.

При желании можешь установить позицию X у камеры в 0 в инспекторе Transform — это сделает перемещение более плавным и аккуратным при разворотах.

Сцена с дублированными платформами и камерой, следящей за крысой
Сцена расширена с помощью дополнительных платформ. Камера привязана к крысе и следует за ней автоматически.

И вот и всё — первая часть завершена! Теперь у тебя есть живая крыса, которая умеет двигаться, прыгать, анимироваться, издавать шаги и гулять по расширенному уровню с камерой-наблюдателем.