Все Гайды Мой Кабинет

Создаём игру Flappy Bird на Unity

Автор: Admin 15 дней назад

Приветствую начинающих разработчиков! В данном уроке мы научимся делать такую популярную игру как Flappy Bird. В данной игре есть 2 важные особенности. Во-первых, здесь происходит бесконечная генерация уровня, отчего у разработчика существенно экономится время на их создание. А во-вторых здесь происходит иммитация полёта птички, хотя по факту птичка стоит на месте, а движется весь окружающий её мир. Данная механика очень редкая, и в основном встречается как раз в играх типа Flappy Bird или ей подобных.

Смысл игры следующий: наш главный персонаж - это птичка, летящая слева направо по оси X. На её пути постоянно попадаются препятствия в виде ящиков, которые птичка должна облетать. Для облёта ящиков, у птички имеется одно лишь действие - взлёт вверх. Вниз она будет падать под действием силы гравитации.

Создание персонажа птички

Ну и первым делом с помощью окна Hierarchy создадим 2д объект, который будет являться нашим персонажем, и назовём его Player. Присвойте данному объекту тег с таким же названием, Player. Добавьте к нему 2 компонента: Rigidbody 2D и Circle Collider 2D.

Далее создайте C# скрипт с названием movePlayer, и заранее присвойте его к нашему персонажу Player. Впишите в скрипт следующий код:

using UnityEngine;

public class movePlayer : MonoBehaviour
{
    private Rigidbody2D rb;
    public float force = 7.0f;

    void Awake()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            rb.AddForce(new Vector2(0, force), ForceMode2D.Impulse);
        }
    }
}

Здесь мы при нажатии на кнопку "пробел" с помощью метода AddForce() заставляем взлетать птичку вверх с определённой силой. Силу взлёта можете исправить в строке #6. На этом создание птички завершено.

Создание заднего фона (баграунда)

Теперь создадим 2д объект, который будет служить баграундом(задним фоном) для игры, назовём его Background. Создадим для него c# скрипт с названием MoveBackground, и сразу присвоим его нашему баграунду. Впишем в скрипт следующий код:

using UnityEngine;

public class MoveBackground : MonoBehaviour
{
    public float speed = 0.01f;

    private void Update()
    {
        transform.Translate(Vector2.left * speed);
    }
}

Единственное что делает этот код, это с помощью метода Translate() постоянно двигает наш баграунд влево со скоростью 0.01f. Ведь как я сказал выше, движение в левую сторону будет производить весь окружающий мир, кроме самой птички.

Теперь нам необходимо создать 2 метки, чтобы мы могли создавать новые баграунды, и удалять старые. Для этого внутри объекта Background создадим ещё два 2д объекта со следующими названиями: Create и Delete.

В окне Hierarchy должна быть следующая структура:

Для удобства понимания, можете объекту Create присвоить зелёный цвет, а объекту Delete - красный(см. рисунок ниже). Объекты Create и Delete растяните по вертикали на всю высоту камеры, и разместите их примерно в таких позициях, как указаны на рисунке ниже.

Смысл следующий: Как только главный персонаж пересечёт зелёный объект Create, то мы должны создать новый баграунд в правой части сцены. А как только игрок пересечёт красный объект Delete, то мы должны удалить текущий объект баграунда вместе с её метками. И перед тем, как мы начнём писать код, проделаем два важных действия.

Во-первых, для наших объектов Create и Delete необходимо создать компоненты Box Collider 2D, и в поле Is Trigger поставить галочку, так как мы будем работать с триггерными методами.

Во-вторых, нам необходимо из нашего объекта Background, создать префаб, который будет иметь такое же название, Background.

ВАЖНО: С этого момента, ВСЕ проводимые манипуляции с баграундом, необходимо проводить не с объектом из окна Hierarchy, а именно с ПРЕФАБОМ, из окна Project.

Ну а теперь перейдём к созданию скриптов. Первым делом, создадим скрипт, который будет создавать наш баграунд на игровой сцене. Для этого создадим c# скрипт, и назовём его CreateBackground. Заранее присвоим его любому объекту, например игровой камере, и впишем в него следующий код:

using UnityEngine;

public class CreateBackground : MonoBehaviour
{
    public GameObject background;

    public void CreateBackground(Transform parent)
    {
        Vector2 posBackground = new Vector2(parent.position.x + 19.2f, parent.position.y);
        Instantiate(background, posBackground, Quaternion.identity);
    }
}

В строке #5 мы создали переменную, которая будет хранить ссылку на префаб баграунда. Поэтому предлагаю заранее с помощью окна Inspector перенести в данное поле префаб баграунда.

В строке #7 мы создали специальный метод CreateBackground(), который с помощью метода Instantiate() создаёт наш баграунд на игровой сцене. Обратите внимание что к позиции по оси X мы прибавляем значение 19.2f. Чтобы правильно расчитать своё значение, которое необходимо прибавить, необходимо ширину вашего баграунда делить на 100, и получаем 19.2. Например, если высота вашего баграунда составляет 1080 пикселей, то необходимо прибавить 10.8f. У меня это значение составляет 19.2, так как ширина моего баграунда 1920 пикселей.

Скрипт, который создаёт баграунд готов. Сейчас создаём C# скрипт, который будет вызывать метод CreateBackground() из данного скрипта при определённом условии. Назовём данный скрипт Pointer, и присвоим его объекту Create, который находиться в ПРЕФАБЕ Background.

Впишем в данный скрипт следующее содержимое:

using UnityEngine;

public class Pointer : MonoBehaviour
{
    private CreateBackground backgroundCreate;

    private void Awake()
    {
        backgroundCreate = FindObjectOfType<CreateBackground>();
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.gameObject.tag == "Player")
        {
            backgroundCreate.CreateBackground(transform.parent);
            Destroy(gameObject);
        }
    }
}

Здесь мы сначала в переменную backgroundCreate получаем ссылку на наш предыдущий скрипт CreateBackground, который находится на объекте нашей камеры, а потом в строке #12 с помощью метода OnTriggerEnter2D() мы проверяем, вошёл ли в нас какой-либо объект. И если этот объект имеет тег Player, то выполняем следующие действия:

  • Запускаем метод CreateBackground() из предыдущего скрипта, отправив в него в качестве аргумента позицию нашего родителя.
  • С помощью метода Destroy() удаляем текущий объект Create, во избежании возможных проблем.

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

Создадим c# скрипт с названием DeleteBackground, и заранее присвойте его объекту Delete, который находиться внутри ПРЕФАБА Background. Впишем в него следующий код:

using UnityEngine;

public class DeleteBackground : MonoBehaviour
{
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.gameObject.tag == "Player")
        {
            Destroy(transform.parent.gameObject);
        }
    }
}

Здесь происходят такие же проверки как и в предыдущем скрипте. То-есть, в строке #5 с помощью метода OnTriggerEnter2D() мы проверяем, вошёл ли в данный объект другой объект, имеющий тег Player. Если да, то с помощью Destroy() мы удаляем родителя, то-есть Background, со всеми его вложенными объектами.

После запуска данного проекта, всё должно работать как надо. Как только персонаж пересечёт зелёную линию, с правой стороны будет создан новый баграунд. А если он пересечёт красную линию, то данный бъект будет удалён. Если всё работает как надо, то идём дальше.

Создание препятствий

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

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

Начнём с создания ящика. Для этого создадим 2д объект, и назовите его block. Присвоим ему компонент Box Collider 2D. Далее, как и в предыдущем примере, в этом же компоненте, в поле Is Trigger ставим галочку, чтобы указать, что мы будем работать с триггерами.

Далее создадим c# скрипт для нашего ящика, с названием MoveBlock, и заранее присвойте его только что созданному объекту block. В сам скрипт впишите следующий код:

using UnityEngine;
using UnityEngine.SceneManagement;

public class MoveBlock : MonoBehaviour
{
    public float speed = 0.01f;

    private void Update()
    {
        transform.Translate(Vector2.left * speed);
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.gameObject.tag == "Killer")
        {
            Destroy(gameObject);
        }

        if (collision.gameObject.tag == "Player")
        {
            SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
        }
    }
}

Если вкратце, то здесь как и с баграундом, мы с помощью метода Translate() постоянно двигаем наш ящик влево со скоростью 0.01f.

В строке #13 с помощью метода OnTriggerEnter2D() мы проверяем вхождение в область нашего объекта. Если в него вошёл объект с тегом Killer, то с помощью метода Destroy() мы удаляем наш объект ящика. Сам объект с тегом Killer, это и есть объект-уничтожитель. Его мы создадим чуть позже. А если объект имеет тег Player, то это означает, что в ящик врезалась наша птичка, и скрипт перезагружает сцену заново, и игра начинается с самого начала.

Поскольку данный ящик мы будем спавнить бесконечно, то сделаем из объекта block префаб, с таким же названием block.

Пришло время для создания спавнера. Для этого создадим пустой объект, и назовём его PointBlock. Поместим его в конец нашего баграунда. Местоположение данного объекта(спавнера) я пометил красной точкой.

Именно в этой точке и будут создаваться наши ящики, и в дальнейшем двигаться влево. И чтобы всё это работало, создадим ещё один c# скрипт с названием SpawnBlock, и заранее присвойте его нашему спавнеру (объекту PointBlock). Впишем в скрипт следующий код:

using UnityEngine;

public class SpawnBlock : MonoBehaviour
{
    public GameObject block;

    private float timeBtwSpawn;
    public float startTimeBtwSpawn = 6f;

    public float startPosition = -5f;
    public float endPosition = 5f;

    private void Start()
    {
        timeBtwSpawn = startTimeBtwSpawn;
    }
    private void Update()
    {
        timeBtwSpawn -= Time.deltaTime;
        if (timeBtwSpawn <= 0)
        {
            Vector2 spawnPos = new Vector2(transform.position.x, Random.Range(startPosition, endPosition));
            Instantiate(block, spawnPos, Quaternion.identity);
            timeBtwSpawn = startTimeBtwSpawn;
        }
    }
}

Данный код каждую 1 секунду спавнит ящик в случайной точке в пределах расстояния от -5 до 5 по оси Y. Обратите внимание, что в строке #5 мы создали переменную block для нашего префаба ящика, который будет спавниться. Поэтому перетащите через Inspector в поле block префаб ящика.

Итак, сам ящик создан. Спавнер ящиков тоже создан. осталось создать уничтожитель ящиков.

Создадим новый 2д объект с названием AreaDeath, и присвойте ему два компонента: Rigidbody 2D и Box Collider 2D. В компоненте Rigidbody 2D отмените гравитацию для данного объекта. Так же данному объекту добавьте тег Killer.

Разместим данный объект по левую сторону игровой сцены. Для удобства, я пометил данный объект синим цветом.

Скрипт-уничтожитель для данного объекта создавать не нужно, поскольку уничтожение ящиков прописано в предыдущем скрипте, под названием MoveBlock.

На этом всё. Можете запустить данный проект и наслаждаться игрой. Если остались вопросы, задавайте их в комментариях, с удовольствием отвечу.

Вы можете отблагодарить автора донатом. Донат

Комментарии

0
Будьте первым, кто оставит комментарий к этому посту
Гости не могут оставлять комментарии. Войдите на Сайт или Зарегистрируйтесь