Блог

Всі статті

Як розробити мінігру, за допомогою ШІ

Не секрет, що сфера ІТ перебуває в постійному розвитку, постійно з’являються нові технології та інструменти. Сучасний світ переживає вибуховий ріст у галузі штучного інтелекту (ШІ), охоплюючи безліч галузей. Світ технологій та ігор змінюється швидше, ніж будь-коли раніше, і інтеграція ШІ стає нормою. Тому фахівцям та компаніям в цілому, необхідно постійно бути на сторожі, щоб не пропустити нові підходи, механізми та можливості.

Саме тому Олександр,  спробував провести експеримент – створення сцени міні гри на основі Unity за допомогою Chat GPT. Метою цього експерименту було отримати подібний досвід і зрозуміти, наскільки Чат може допомогти прискорити розробку подібних проєктів. Сьогодні він розбере цей кейс з вами.


Ну що ж, розпочнімо. У якості графічного двигуна мною було обрано 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 – Створення “героя”

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

Запит – “Напиши скрипт для того, щоб об’єкт підійматися вгору поки утримуєш тап”

Відповідь – 

‘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. Очевидно, що результати роботи платної (крайньої) версії будуть кращими.

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