Блог

Все статьи

Cоздание мини-игры, с помощью ИИ

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

Именно поэтому Александр решил провести эксперимент – создание сцены мини-игры на основе Unity при помощи GPT Chat (Чат). Целью этого эксперимента было получить аналогичный опыт и понять, на сколько Чат может помочь ускорить разработку подобных проектов.

Итак, начнем. В качестве графического движка был выбран Unity среды разработки 2022.3.12f1. Почему именно Unity? Ну, во-первых, я слышал что это очень популярный движок с развитым IDE и хорошей поддержкой. Во-вторых, он сразу позволяет разворачивать игру на более чем одной платформе – например для iOS и Android. Для сравнения с помощью нативного SpriteKit от Apple возможно создать игру только для платформы iOS.  В качестве ИИ была выбрана бесплатная версия GPT Chat 3.5 (далее Чат). Сразу хочу отметить, что до этого момента у меня не было опыта работы ни с первым, ни со вторым. Из опыта у меня была только разработка на iOS, но тем интереснее мне показался этот эксперимент. 

Итак, давайте по порядку. Для начала я составил такой план из двух пунктов:

  • Найти и выполнить туториал по созданию игры на Unity, чтобы получить базовое представление в предметной области.
  • Попробовать создать подобную/другую игру, но уже с помощью Чата.

По первому пункту не получилось найти подходящий туториал для создания 2D игры. На глаза попался мануал для 3D. После первых часов опытов я понял, что продолжение работы по этому руководству будет чрезмерной тратой времени. Во-первых, была существенная разница между версиями моей IDE и той, которая была описана в туториале – многие функции/контролы и их расположение не совпадали друг с другом. Во-вторых, стало понятно, что в мануале для создания 3D игры много лишней информации, которая не понадобится в эксперименте. Поэтому, получив первичное представление о Unity, я решил сразу перейти ко второму пункту и начать создавать свою игру, но уже с помощью Чата.

Задумка для игры была самая простая – создать сцену, на которой слева от экрана вверх и вниз летает герой. При лонг-тапе он поднимается вверх, а при отпускании- опускается вниз. Герой должен стрелять автоматически. Справа (из рандомных точек по оси Y) должны вылетать монстры и двигаться навстречу герою. При попадании пули в монстра он должен исчезать. Также, фоном для сцены должен был быть прокручивающийся бесконечный бэкграунд.

На первый мой запрос – “Как создать подобную мини-игру?” (Описание дал ему выше) Чат ответил перечислением шагов с кратким описанием каждого – “Определение игровой механики, Выбор языка и среды разработки, Создание графики, Разработка игрового движка, Интерфейс пользователя, Тестирование, Публикация, Маркетинг и продвижение, Поддержка и обновления”

Так повторилось несколько раз в разных вариациях – я понял что общими запросами я многого от него не добьюсь. Вспоминая материал из туториала про 3D игру я попробовал разбить большую задачу на маленькие:

  • Создать объект “герой” с необходимой физикой движения
  • Добавление “герою” возможности стрелять “пулями” 
  • Создать объект “монстр” с необходимой физикой движения 
  • Сделать так, чтобы монстр исчезал после столкновения с пулей
  • Создать бекграунд с инфинити скроллом
  • Добавить изображения для всех объектов

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

Вот как дальше двигалась работа по этапам.

Этап 1 – Создание “героя”

Для начала я создал пустой модель/объект и добавил его на мою сцену. После этого было необходимо описать поведение Героя в специальном файле со скриптом (С#). Составить такой скрипт я попросил Чат:

Запрос – “Напиши скрипт  для того чтобы объект подымался вверх пока удерживаешь тап”
Ответ –

‘using UnityEngine;

public class LiftObject : MonoBehaviour

{

    private bool isTapping = false;

    private Vector3 initialPosition;

    public float liftSpeed = 1.0f; // Скорость подъема объекта

    void Update()

    {

        if (Input.touchCount > 0)

        {

            Touch touch = Input.GetTouch(0); // Предполагаем, что используется первое прикосновение

            if (touch.phase == TouchPhase.Began)

            {

                isTapping = true;

                initialPosition = transform.position;

            }

            else if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled)

            {

                isTapping = false;

            }

        }

        else

        {

            isTapping = false;

        }

        if (isTapping)

        {

            // Поднимаем объект вверх

            Vector3 newPosition = transform.position + Vector3.up * liftSpeed * Time.deltaTime;

            transform.position = newPosition;

        }

    }

}

В этом скрипте мы проверяем, удерживает ли пользователь тап (прикосновение) к экрану. Если это так, то объект будет подниматься вверх с заданной скоростью liftSpeed. Когда пользователь отпускает экран, подъем останавливается.

Чтобы использовать этот скрипт, просто прикрепите его к объекту в Unity. Вы также можете настроить liftSpeed, чтобы регулировать, насколько быстро объект будет подниматься.

Далее для экономии вашего времени я не буду указывать образцы кода – просто будут запросы и общие результаты ответов.

Т.к. ранее мне не доводилось работать со скриптами для объектов – я спросил:
Запрос – “Как прикрепить скрипт к объекту/спрайту в юнити?”

Ответ –

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

  • Создайте новый скрипт: откройте свой проект в Unity. На панели “Project”, щелкните правой кнопкой мыши по папке, в которой вы хотите создать скрипт. Выберите “Create” -> “C# Script” (если вы пишете на C#) или “Create” => “JavaScript” (если вы используете UnityScript).
  • Настройте скрипт: переименуйте скрипт в соответствии с его назначением, щелкнув на нем правой кнопкой мыши и выбрав “Rename”. Дважды щелкните по скрипту, чтобы открыть его в выбранной вами интегрированной среде разработки (например, Visual Studio или Visual Studio Code).
  • Присоедините скрипт к спрайту: перейдите к сцене, где находится ваш спрайт. В окне “Hierarchy” выберите спрайт, к которому вы хотите присоединить скрипт. В компоненте “Inspector” на панели справа, найдите секцию “Add Component”. Введите имя вашего скрипта в поле поиска и выберите его из выпадающего списка. Теперь ваш скрипт прикреплен к выбранному спрайту. Вы можете начать редактировать скрипт, добавлять логику и взаимодействие с этим спрайтом. Когда вы запустите сцену, скрипт будет выполняться при взаимодействии со спрайтом или в соответствии с вашей логикой.”

Как мы видим – Чат предлагал не только очередность действий, но и описывал саму работу с IDE, что мне, как новичку, было очень полезно на первых этапах.

После запуска программы я обнаружил, что герой умеет только подниматься при лонг-тап, но не опускается при убирании пальца с экрана. Но, тут вопросов к Чату нет – какой был запрос – такой и результат)).   

Запрос – “Что нужно добавить в скрипт чтобы объект опускался вниз если нету тапа?”

Ответ – Чат выдал скрипт, который уже позволял объекту опускаться.

Далее я обнаружил что мой Герой в крайних точках может выходить за пределы экрана


Запрос – “Измени скрипт что бы объект не мог выходить за пределы экрана”


Ответ – Чат переписал скрипт с новыми ограничениями, но почему-то заложил константы minY и maxY для того чтобы я мог самостоятельно ограничивать ход Героя. 

После того как я попросил его “добавить ограничение не константами а реальными размерами экрана” – я получил скрипт который уже удовлетворял всем требованиям для первого этапа.

Этап 2 – Добавление опции стрельбы “пулями”

Вначале я попытался решить задачу одним “волшебным” запросом


Запрос – “объект должен стрелять”


Ответ – Чат это понял по своему и обновил скрипт Героя – дал ему возможность перемещаться по экране в 4-х направлениях и стрелять при нажатии кнопки.

Запрос – “Нет, ты должен использовать предыдущий скрипт – там где объект может перемещаться вверх/вниз

Просто добавь в него автоматическую стрельбу белыми прямоугольниками по направлению слева направо с интервалом 0.5 секунды”

Ответ – Чат поправил скрипт, но в  результате получилось. что прямоугольники вылетали не из Героя, а появлялись перед ним и летели вправо.

Запрос – “Сделать так чтобы начальная точка полета прямоугольника рассчитывалась от середины высоты текущего объекта”

Ответ – Чат написал новый скрипт и посоветовал мне добавить новый объект для Пули, т.к. Герой будет его использовать при стрельбе.

После добавления нового пустого объекта на сцену, я попросил Чат написать для него скрипт, но далее оказалось что пуля летит слева направо как и требовалось, но при этом смещается вниз по оси Y. Для устранения этого в объекте Пуля  пришлось отключить опцию гравитации.

Последним испытанием на этом этапе стала корректная дислокация выпущенных пуль, когда они покидают пределы экрана. Согласно предложенному Чатом коду, Пули должны были уничтожаться в функции обновления объекта (вызывается постоянно для каждого объекта):

void Update()

    {

        // Уничтожаем пулю, когда она выходит за пределы экрана

        if (!GetComponent<Renderer>().isVisible)

        {

            Destroy(gameObject);

        }

    }

К сожалению, при запуске приложения сразу стала появляться ошибка – MissingReferenceException. А если не удалять объект – он оставался в памяти.


Все предложения Чата по поводу проверок на NULL и его комбинаций с проверками, типа isVisible, не имели успеха. Потратив какое-то время на всевозможные вариации запросов к Чату, которые водили меня по кругу, я обратился к Google, где удалось найти вариант решения.
Для Пули необходимо было воспользоваться функцией жизненного цикла объекта и в ней вызвать замыкание по которому владеющий Пулей объект (Герой) удалит её.

void OnBecameInvisible()

    {

        // Проверяем, есть ли подписчики на событие, и вызываем его

        OnBulletInvisible?.Invoke();

    }

Этап 3 – Добавление “Монстров”

Для создания и оживления Монстров я, по сути, проделал все те же шаги что и для Пули. Единственным отличием было то, что Пулю порождал Герой и с монстрами необходимо было поступить похожим образом – создать для них свой объект (MonsterSpawner), который смог бы ими “стрелять”

Запрос – “Нужно чтобы на экран вылетали объекты (монстры) с правой стороны и летели вдоль оси Х в левую сторону. Интервал появления монстров 2 секунды.”

Ответ – Чат предложил мне два скрипта – Скрипт для монстров (MonsterScript.cs) и  Скрипт для создания монстров (MonsterSpawner.cs)

Запрос – “Где использовать скрипт MonsterSpawner? прикрепить к какому-то объекту?”

Ответ – “Да, вы можете прикрепить скрипт MonsterSpawner к какому-то объекту в вашей сцене. Создайте пустой GameObject, выберите его в иерархии, а затем прикрепите скрипт MonsterSpawner к этому объекту. После этого у вас будет возможность настроить параметры спаунера монстров (например, префаб монстра, интервал появления и т. д.) через инспектор Unity”

Далее нужно было сделать убийство монстра.


Этап 4 – Сделать так чтобы монстр исчезал после столкновения с пулей

Запрос – “Монстры при столкновении с пулей должны исчезать.”

Ответ – “Вам потребуется добавить Box Collider 2D к вашим монстрам и пуле, чтобы обнаруживать столкновения.” 

Также Чат выдал два обновленных скрипта для Пули и Монстра, которые учитывали столкновение и новый скрипт для MonsterSpawner, который делал удаление монстра при его столкновении и срабатывании кложуры. 

Подобные манипуляции я проделал и с пулей – теперь у меня уже вырисовывалась сцена которая уже была на что то похожа. 

Этап 5 – Создать бекграунд с бесконечным скроллом

Для бекграунда я решил использовать принтскрин изображения со звездным небом. Задумка была в том, чтобы научить эту картинку бесконечно, и главное, бесшовно прокручиваться по оси Х в виде бэкграунда для сцены.

Запрос – “Как сделать бесконечный фон который двигается справа налево?”

Ответ – “Для создания бесконечного фона, который двигается справа налево, вы можете использовать два экземпляра фона, расположенных рядом, и перемещать их по мере движения, чтобы создать эффект бесконечности.“

Вариант с двумя картинками меня не устраивал

Запрос – “Нужно создать бесконечный фон из одной картинки”

Ответ – “Для создания бесконечного фона из одной картинки в Unity, вы можете использовать скрипт, который будет перемещать текстуру фона по горизонтальной оси, создавая эффект бесконечности.”

Фон не двигался. Чат пытался давать разные советы по настройке компонентов, но было ощущение, что он просто предлагает мне их по кругу.
Далее я попробовал перейти на английский язык, так как читал что Чат его понимает лучше и дает более точные ответы. Результат не изменился – мы продолжили ходить по кругу.
Потратив изрядное количество времени, я обратился к Google  и нашёл решение там. Для инфинити бэкграунда необходимо было создать объект совершенно другого типа – Quad, создать для него Материал на основе моей картинки и определенным образом настроить для него шейдер с текстурой.

После всего этого остался, наверное, последний момент:
Вопрос – “Как сделать чтобы пули не перекрывались фоном?”

Ответ – “Чтобы пули не перекрывались фоном, вы можете использовать систему слоев в Unity. Убедитесь, что ваш фон и пули находятся на разных слоях, и настройте их порядок слоев так, чтобы фон был ниже пуль.”

Таким образом я изменил Z-иерархию для слоев, и всё заработало. Осталось только картинки.

Этап 6 – Добавить картинки для всех объектов

Для добавления картинок к каждому объекта Чат мне уже не понадобился. Это я уже знал из туториала. Я получил желаемый результат, создав спрайты  с каждой картинкой и прикрепив их к нужным объектам.

Выводы

  • Чат действительно ускоряет процесс разработки, предлагая готовые скрипты по запросу и и обычно снабжая их сопутствующими инструкциями — как и какой объект добавить и настроить.
  • Качество ответов напрямую зависит от качества запросов – чем точнее запрос с указанием деталей и нюансов, тем более вероятность, что ответ Чата сработает с первого раза
  • Некоторые проблемы Чат не смог решить, пришлось искать рещение самостоятельно – мемори лики, корректная работа инфинити бэкграунда, выбор правильных шейдеров.
  • Для создания мини-игр необходимы навыки работы с Unity.
  • По ощущениям, Чат может сэкономить 20-30% времени на разработку. Для каждого типа игры необходимо понимание, как всё должно взаимодействовать и какие нюансы существуют для разных кейсов.
  • Чем выше уровень владения Unity, тем эффективней можно работать с Чатом.
  • Ответ от Чата будет более полным, если запрос будет составлен четко и полно. Хочу отметить, что что в ходе эксперимента использовалась бесплатная версия 3.5. Очевидно, что результаты работы платной версии будут лучше.

Автор Александр Бондарь