Блог онлайн школы Пиксель

Уроки Unity для школьников: Как сделать 2D-платформер

Какие виды игр больше всего любите вы: лабиринты, полосы препятствий или что-то еще? Сегодня расскажем, как сделать 2D-платформер в Unity — это жанр, в котором необходимо путешествовать по уровням. Играть очень увлекательно, а разрабатывать еще интереснее - покажем, как юным программистам создать такую игру на базе Unity.
На YouTube-канале школы «Пиксель» вы найдете множество уроков по Unity для начинающих, а также другие плейлисты, которые пригодятся для дальнейшего развития в программировании или подготовке к экзаменам.

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

Перед началом создания 2D-платформера на Unity запускаем программу и создаем новый двухмерный проект. Присваиваем ему имя и нажимаем Create Project.

Спрайты для игры можно нарисовать самостоятельно или найти готовые в интернете, например, по ссылке Download the latest indie games - itch.io.
Нам понадобятся спрайты персонажа, платформ и фона, скачиваем их и импортируем в наш проект.

С помощью спрайта земли соберем одну большую платформу. Для удобства переместим окно игры рядом с окном сцены. Благодаря комбинации клавиш CTRL+D дублируем блок земли.  Если при перетаскивании зажимать клавишу CTRL, то перемещение будет производиться по невидимой сетке - дублируем до тех пор, пока не сделаем необходимую платформу. Создадим пустой объект и поместим в него все блоки, теперь платформу можно перемещать и масштабировать целиком.

Создаем Canvas (полотно), на котором разместим задний фон. Масштаб полотна зададим по размеру экрана, для этого установим разрешение вручную.

Уроки Unity для школьников: как увеличить платформу


Для заднего фона импортируем структуры, которые были найдены в интернете. Далее понравившуюся текстуру устанавливаем в качестве фона и выбираем для нее цвет. Теперь установим тип изображения. Параметр Tiled равномерно покроет заданной текстурой все пространство, не растягивая ее, а именно повторяя. Позицию текстуры установим по всей ширине и высоте. Выбираем этот параметр с зажатой клавишей Alt. Немного изменим цвет. Установим камеру для полотна и таким образом переместим все игровые объекты на передний план.

Переходим в папку со спрайтами персонажа. Возьмем первый кадр из анимации IDLE и переместим на сцену. Увеличиваем персонажа и убираем размытие у всей его анимации. Это необходимо сделать у всех пиксельных спрайтов.

Добавление Box Collider 2D-платформе в Unity


Создадим папку для анимаций и аниматор в ней для построения логики перехода между анимациями.

Теперь делаем непосредственно самого игрока и переместим в него спрайт.

Открываем окно анимации и перемещаем в удобное место. Создаем анимацию IDLE и сохраняем в ранее созданную папку для анимаций. Выделяем все кадры и перемещаем.

Скорость анимации можно изменить 2 способами:
  • растянуть ее в этом окне;
  • поменять значение скорости в аниматоре.

Откроем аниматор. Выбираем спрайт игрока, а в аниматоре анимацию IDLE. Здесь можно выставить скорость воспроизведения анимации. Запускаем игру и проверяем. При включенной игре можно подобрать оптимальную скорость.

Создание анимации бега в Unity
Проверяем переход между анимацией покоя и бега.

Далее сделаем обратный переход и у каждого перехода уберем галочку с Has Exit Time. Устанавливаем продолжительность перехода 0. Данные параметры нужны для плавного перехода между анимациями, что в данном случае не требуется.

Теперь создадим булевую переменную isMoving, которая будет переключать персонажа из состояния покоя в движение и обратно. Условием для перехода здесь будет isMoving равно true. Переход из бега в покой isMoving равно false. Запустим и проверим переключение анимаций.

Для игрока сделаем капсульный 2D-Collider с настройкой размеров. Тут важно не путать его с обычным, который предназначен для 3D-объектов.

Написание скриптов в Unity


Создадим для этого отдельную папку. Обозначаем скрипт. Удаляем комментарии.

Добавим переменную для задания скорости движения игрока и вектор, задающий направление перемещения, а также ссылку на компонент rigidbody. В функции старт присвоим этот компонент в переменную. Функция старт выполняется один раз при запуске игры, в отличие от функции Update — она вызывается каждый кадр игры. В этой функции мы вызовем функцию Move, отвечающую за движение персонажа.

Функция Move начнется с получения направления движения с клавиатуры. Horizontal означает, что мы считываем клавиши a и d, а потом в соответствии с этим сохраняем в Input число от -1 до 1. Чем дольше мы нажимаем клавишу а, тем ближе число подбирается к -1, соответственно и персонаж быстрее двигается в левую сторону. С правой стороной тоже самое, только нажимать нужно клавишу d.
Далее к координатам игрока прибавляем перемещение, которое рассчитывается по формуле: направление умножается на скорость и на время между кадрами игры. Скорость, умноженная на время - это расстояние, которое мы пройдем персонажем в сторону направления вектора input.

Создадим ссылку на компонент SpriteRenderer. Чтобы поворачивать нашего персонажа по направлению движения, добавим условие в Move. Если направление не равно нулю, то есть мы перемещаем персонажа, то поворачиваем спрайт в соответствующую сторону. Вложенное условие как раз и нужно для того, чтобы активировать поворот, если мы повернем персонажа.

Сделаем Sprite Renderer публичной переменной, чтобы поместить в нее ссылку на Sprite Renderer персонажа. Перемещаем спрайт в это поле. Запускаем и проверяем. Поворот работает.

Создание скрипта в Unity для управления переключением анимаций


Создадим 2 переменные:
  1. переменная, в которой будет храниться ссылка на аниматор;
  2. переменная, которая отвечает за включение и отключение анимации бега. 
В функции старт сохраним компонент аниматора в переменную. В функции update будем синхронизировать значение переменной isMoving с одноименной переменной из аниматора.
В скрипте передвижения персонажа тоже создадим такую переменную и дополнительно объект класса скрипта анимаций персонажа. В функции Start сохраним компонент скрипта смены анимаций в переменную, а в функции Move будем переключать состояние переменной isMove в соответствующем условии:
  • если направление не равно нулю, то есть движение;
  • если значение направление равно нулю, то положение не меняется.
В конце отправляем значение переменной движения в скрипт смены анимаций, который, в свою очередь, поменяет переменную в аниматоре.

Запускаем и проверяем.

Аналогичным образом в игру добавляются и другие анимации: чем больше механик игры, тем сложнее будет логика для их реализации.

Мы завершили создание 2D-платформера на Unity. Теперь вы можете экспериментировать самостоятельно, например, менять персонажа, среду или пробовать различную скорость переходов. Видеоинструкция “Как сделать 2D-платформер на Unity” доступна по ссылке — смотрите и создавайте свою игру.


На нашем YouTube-канале доступны и другие бесплатные уроки по Unity, которые помогут познакомиться с программой и сделать первые шаги. Чтобы досконально разобраться в кодинге и создании игр, стоит обратить внимание на специализированные курсы. Школа программирования «Пиксель» предлагает занятия Unity для школьников с 10 лет - каждый ребенок сможет попробовать свои силы в разработке и защитить собственный проект. Окунитесь в мир IT с профессиональными программистами!


Скрипт PlayerAnimation


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

public class PlayerAnimations : MonoBehaviour
{
    public Animator animator;
    public bool IsMoving;
    public bool IsFlying;

    void Start()
    {
        animator = GetComponent<Animator>();
    }


    void Update()
    {
        animator.SetBool("isMoving", IsMoving);
        animator.SetBool("IsFlying", IsFlying);
    }
    public void Jump()
    {
        animator.SetTrigger("Jump");
    }
}

Скрипт PlayerMovement


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

public class PlayerMovement : MonoBehaviour
{
    public float speed;
    private float jumpForce = 5f;
    private Vector3 groundCheckOffset;
    private bool IsMoving;
    private Vector3 input;
    public bool isGrounded;
    private Rigidbody2D rb;
    public SpriteRenderer sprite;
    private PlayerAnimations animations;

    public LayerMask groundMask;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        animations = GetComponentInChildren<PlayerAnimations>();
    }

    void Update()
    {
        Move();
        CheckGround();
        if (Input.GetKeyDown(KeyCode.Space))
        {
            if (isGrounded)
            {
                Jump();
                animations.Jump();
            }
        }
        animations.IsMoving = IsMoving;
        animations.IsFlying = IsFlying();
    }

    private void Move()
    {
        input = new Vector2(Input.GetAxis("Horizontal"), 0);
        transform.position += input * speed * Time.deltaTime;

        if (input.x != 0)
        {
            IsMoving = true;
            if (input.x > 0)
            {
                sprite.flipX = false;
            }
            else
            {
                sprite.flipX = true;
            }

        }
        else IsMoving = false;
        animations.IsMoving = IsMoving;
    }
    private void Jump()
    {
        Debug.Log("Jump");
        rb.AddForce(transform.up * jumpForce, ForceMode2D.Impulse);
    }

    private void CheckGround()
    {
        float rayLength = 0.3f;
        Vector3 rayStartPosition = transform.position;
        RaycastHit2D hit = Physics2D.Raycast(rayStartPosition, rayStartPosition + Vector3.down, rayLength, groundMask);
        Debug.DrawRay(rayStartPosition, rayStartPosition + Vector3.down, Color.red);
        if (hit.collider != null)
        {
            isGrounded = true;
        }
        else {
            isGrounded = false;
        }
    }
    private bool IsFlying()
    {
        if (rb.velocity.y < 0)
        {
            return true;
        }
        else {
            return false;
        }
    }
}

Unity для детей Бесплатные видеоуроки