Привет! В этом пошаговом уроке мы вместе создадим простой
2D платформер на движке Unity. Этот
гайд подходит для новичков: тебе не нужно быть экспертом, мы всё
объясним понятно и подробно. Мы будем использовать встроенную
физику Unity 2D, добавим немного анимации и научимся
работать со спрайт-листами.
Чтобы пройти урок, тебе понадобятся некоторые ресурсы:
спрайты, звуки и скрипты.
📦 Скачать архив .zip для проекта 📦
— в нём есть всё, что нужно для старта разработки платформера на Unity.
Запусти Unity и создай новый 2D-проект. Для начала выбери 2D Built-in Render Pipeline — или любой другой 2D-шаблон.
Сначала мы подготовим основу игры: добавим объект земли и персонажа.
Распакуй скачанный .zip архив и импортируй в Unity спрайт
largeGround. Перетащи largeGround в сцену и
переименуй созданный GameObject в Ground.
Выбери Ground в иерархии. В инспекторе:
0.
Теперь добавим игрока. Импортируй спрайт-лист ratIdle
(он тоже в архиве). Unity, скорее всего, автоматически нарежет его. Но
при автоматической нарезке спрайт-листа возможна расцентровка
изображения, что приведёт к дёрганной анимации. Лучше сами сделаем
это. Этот спрайт лист настроен на 4*5 спрайтов.
ratIdle в папке Assets.Multiple.
4, Ряды (R): 5, и нажми
Slice.
Разверни спрайт-лист — теперь в нём должно быть 20 кадров. Перетащи первый кадр в сцену. Переименуй созданный GameObject в Rat.
Выбери объект Rat и сделай следующие настройки:
Player.0.Interpolate.
Чтобы прыжки работали, нужно ещё указать, что такое “земля”. Выдели
объект Ground и задай ему Layer как
Ground. Если слоя с таким названием нет — создай его.
Пора заставить нашу крыску двигаться! Создадим скрипт, который будет отвечать и за бег, и за прыжки.
В папке Assets кликни правой кнопкой мыши и создай
новый MonoBehaviour-скрипт. Назови его PlayerMove. Этот
скрипт будет использовать компонент Rigidbody2D для
перемещения игрока с помощью встроенной физики Unity. Мы также добавим
прыжок, который будет применять силу вверх по оси Y. Для определения
того, стоит ли игрок на земле, мы воспользуемся
Physics2D.OverlapPoint. На самом деле использование
OverlapCircle или OverlapBox даст более
надёжную проверку касания земли, но для понимания базового принципа
платформеров нам сейчас достаточно OverlapPoint.
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 и перемести чуть ниже лапок крысы (но
вне её коллайдера).
Теперь снова выбери Rat. В компоненте PlayerMove:
Ground Check.
What Is Ground выбери слой Ground.
💡 Совет: Если слой Ground не
отображается в списке, убедись, что ты выделил объект земли и добавил
нужный слой.
Нажми Play — теперь крыса должна двигаться влево и вправо (с помощью стрелок или A/D) и прыгать, когда стоит на земле.
Крыса теперь умеет двигаться и прыгать — но всё время смотрит в одну сторону. Давай научим её разворачиваться в сторону движения. Для этого мы добавим новую переменную в скрипт и напишем функцию, которая будет "отражать" спрайт при смене направления.
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 — она должна соответствовать исходному
направлению спрайта (если твоя крыса изначально смотрит влево).
Готово! Теперь крыса бегает, прыгает и смотрит в ту сторону, куда движется. Маленькая деталь, но она добавляет жизни всей сцене.
Начнём анимировать нашу крысу! Для начала добавим компонент Animator и создадим контроллер.
В иерархии выбери GameObject Rat. В инспекторе нажми Add Component и выбери Animator.
Затем в окне Assets кликни правой кнопкой и создай
новый Animator Controller. Назови его
RatAnimator.
Теперь присвой контроллер RatAnimator полю
Controller в компоненте Animator у объекта
Rat.
Давай оживим крысу с помощью её первой анимации — петли ожидания (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, чтобы анимация выглядела более плавной.
Пора анимировать движение крысы! Давай создадим анимацию бега и настроим переходы между состояниями.
Сначала импортируй спрайт ratRun из архива в папку
Assets.
Так же как мы делали для ratIdle в шаге 1, выбери спрайт
ratRun в папке Assets, установи
Sprite Mode как Multiple и нажми
Apply. Затем открой Sprite Editor, выбери
Slice → Grid by Cell Count, укажи Колонки (C):
4 и Ряды (R): 5, нажми Slice и
Apply.
Выдели объект Rat в иерархии. В окне
Animation нажми на выпадающий список рядом с
IdleRatAnimation и выбери
Create New Clip. Назови новую анимацию
RunRatAnimation.
(Убедись, что объект Rat выбран в иерархии — иначе Unity не даст
добавить новую анимацию.)
В окне Assets разверни ratRun и выдели все 20 кадров:
кликни по первому, зажми Shift и кликни по
последнему. Перетащи все выделенные кадры в окно
Animation, чтобы заполнить временную шкалу.
Открой окно Animator. Если его не видно — включи через Window → Animation → Animator.
По умолчанию, IdleRatAnimation — начальное состояние. Мы
создадим параметр типа Float, чтобы управлять
переходами между ожиданием и бегом.
Speed.
IdleRatAnimation →
Make Transition → выбери
RunRatAnimation.
RunRatAnimation к
IdleRatAnimation.
Теперь настроим сами переходы:
IdleRatAnimation → RunRatAnimation.
Speed должен быть Greater than
0.1.
RunRatAnimation → IdleRatAnimation.
Speed Less than
0.1.
Чтобы управлять переходами между анимациями, мы создадим простой
скрипт, который будет передавать информацию о движении в Animator. Он
будет переключаться между Idle и Run в
зависимости от скорости крысы.
В папке Assets создай новый
MonoBehaviour-скрипт и назови его
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.
Готово! Теперь при запуске сцены крыса будет автоматически переключаться между анимациями ожидания и бега в зависимости от своего движения.
Давай создадим анимацию прыжка для нашей крысы. У нас нет отдельного
спрайта для прыжка, но мы можем повторно использовать
ratRun с уменьшенной скоростью — получится эффект прыжка.
Выдели объект Rat в иерархии. В окне
Animation нажми на выпадающий список и выбери
Create New Clip. Назови новую анимацию
JumpRatAnimation.
В Assets разверни спрайт-лист ratRun. Выдели все 20
кадров (первый → Shift → последний), затем перетащи
их в таймлайн окна Animation.
Открой окно Animator. Сейчас мы добавим параметр и свяжем его с логикой прыжка.
Перейди на вкладку Parameters и добавь новый параметр
типа Bool с именем isJumping.
Настроим переходы следующим образом:
isJumping == true.isJumping == true.isJumping == false.
Наконец, выдели состояние JumpRatAnimation и установи
Speed на 0.2, чтобы бег выглядел как
прыжок.
Теперь свяжем анимацию прыжка с фактическим состоянием крысы. Для
этого мы получим доступ к переменной 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);
}
}
}
И всё! Больше ничего настраивать не нужно. Теперь анимация прыжка будет включаться автоматически, как только крыса окажется в воздухе — прыгая вверх или падая вниз.
Добавим немного жизни крысе — она будет издавать звуки шагов во время бега. Мы реализуем это с помощью события в анимации, которое вызовет функцию из нового скрипта.
В папке Assets создай новый
MonoBehaviour-скрипт и назови его
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().
Готово! Теперь, когда крыса дойдёт до нужного кадра во время бега, она издаст звук шага. Можно добавить несколько таких событий, чтобы синхронизировать их с каждым шагом.
Давай немного расширим уровень и настроим камеру, чтобы она следовала за крысой. Так у нас появится больше пространства для тестирования и подготовки к следующей части.
Сначала преврати исходный объект земли в префаб. Выдели Ground в иерархии и перетащи его в папку Assets, чтобы создать префаб.
Теперь перетащи этот префаб обратно в сцену несколько раз, чтобы создать дополнительные платформы. Расположи их на разных горизонтальных (и при желании — вертикальных) уровнях, чтобы добавить немного прыжкового вызова.
Затем выбери Main Camera в иерархии и перетащи её внутрь объекта Rat. Теперь камера станет дочерним объектом крысы и будет следовать за ней при движении.
При желании можешь установить позицию X у камеры в 0 в
инспекторе Transform — это сделает перемещение более плавным и
аккуратным при разворотах.
И вот и всё — первая часть завершена! Теперь у тебя есть живая крыса, которая умеет двигаться, прыгать, анимироваться, издавать шаги и гулять по расширенному уровню с камерой-наблюдателем.