Създаване на мини-игра с помощта на AI
Не е тайна, че областта на информационните технологии се намира в постоянно развитие, непрекъснато се появяват нови технологии и инструменти. Съвременният свят преживява голям растеж в областта на изкуствения интелект (ИИ), който обхваща множество индустрии. Светът на технологии и игри се променя по-бързо, отколкото някога, и интеграцията на ИИ става норма. Затова специалистите, както и компаниите като цяло, трябва постоянно да бъдат внимателни, за да не пропуснат нови подходи, механизми и възможности.
Точно затова Александър реши да направи експеримент – създаването на сцена за мини-игра, базирана на Unity с помощта на GPT Чат . Целта на този експеримент беше да получи сходен опит и да разбере до каква степен Чатът може да помогне за ускоряването на разработката на подобни проекти.
Нека да започнем. Като графичен двигател беше избран Unity от разработчиците на 2022.3.12f1. Защо точно Unity? На първо място, чувал съм, че това е много популярен двигател с развита IDE и добра поддръжка. Второ, той веднага позволява да се разгърне играта на повече от една платформа – например, за iOS и Android. За сравнение, с помощта на нативния SpriteKit от Apple, е възможно да се създаде игра само за платформата iOS. За ИИ беше избрана безплатната версия на GPT Чат 3.5 (по-нататък Чат). Искам веднага да отбележа, че до този момент нямах опит с нито единия, нито с другия. Аз имах опит само в разработка за iOS и точно затова експериментът ми се стори много интересен.
Нека действаме по стъпки. Най-напред съставих такъв план, който се състои от две точки:
- Намерана и изпълнение на урока за създаване на игра в Unity, за да получа основно представяне в областта на игрите.
- Опит да се създаде подобна/различна игра, но вече с помощта на Чат.
По първия въпрос не успях да намеря подходящия урок за създаване на 2D игра. Попаднах на ръководство за 3D. След първите часове на експерименти осъзнах, че продължаването на работата по това ръководство би било загуба на време. Първо, имаше съществена разлика между версиите на моята IDE и тази, описана в ръководството – много функции/контроли и техните местоположения не съвпадаха помежду си. Второ, стана ясно, че ръководството за създаване на 3D игра съдържа много ненужна информация, която няма да бъде необходима в експеримента. Ето защо, след като придобих първоначална представа за Unity, реших да премина направо към втората точка и да започна да създавам своя собствена игра, но с помощта на Chat.
Идеята за играта беше най-обикновена – да се създаде сцена, в която героят лети нагоре-надолу в лявата част на екрана. При продължително натискане на бутона той се издига нагоре, а когато го освободите, се спуска надолу. Героят трябва да стреля автоматично. Отдясно (от произволни точки по оста Y) трябва да летят чудовища и да се движат към героя. Когато куршумът попадне в чудовище, то трябва да изчезне. Също така фонът на сцената трябва да бъде превъртащ се безкраен фон.
На първото ми запитване – „Как да създам такава мини-игра?“ (дадох му описанието по-горе) – Чат отговори, като изброи стъпките с кратко описание на всяка от тях: „Определяне на механиката на играта, Избор на език и среда за разработка, Създаване на графики, Разработване на игрови двигател, Потребителски интерфейс, Тестване, Публикуване, Маркетинг и популяризиране, Поддръжка и актуализации“.
Този отговор се повтори няколко пъти в различни варианти – разбрах, че няма да получа много от него с общи запитваниня. Спомняйки си материала от урока за 3D играта, се опитах да разделя голямата задача на малки:
- Създаване на обект „герой“ с необходимата физика на движение
- Добавяне към „героя“ способността да изстрелва „куршуми“
- Създаване на обект „чудовище“ с необходимата физика на движение
- Изчезване на чудовището след сблъсъка с куршум
- Създаване на фон с безкрайно превъртане
- Добавяне на изображения за всички обекти
След това запитванията ми придобиха различен смисъл за Chat и той започна да издава конкретен код и действия с него.
Ето как работата напредваше поетапно.
Стъпка 1 – Създаване на „герой“
Като начало създадох празен модел/обект и го добавих към сцената. След това беше необходимо да опиша поведението на героя в специален скриптов файл (C#). За да съставя такъв скрипт, помолих Chat:
„Напишете скрипт, който да накара обект да се вдига нагоре, докато задържате tap“.
Отговор –
‘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, трябва да следвате следните стъпки:
- Създайте нов скрипт: отворете проекта си в 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. За да поправя това, трябваше да деактивирам опцията за гравитация в обекта Bullet.
Последната проверка на този етап беше правилното изместване на изстреляните куршуми, когато те напуснат екрана. Според кода, предложен от Чата, куршумите трябваше да бъдат унищожени във функцията за обновяване на обекта (извиквана непрекъснато за всеки обект):
void Update()
{
// Знищуємо кулю, коли вона виходить за межі екрана.
if (!GetComponent<Renderer>().isVisible)
{
Destroy(gameObject);
}
}
За съжаление при стартирането на приложението веднага започна да се появява грешка – MissingReferenceException. И ако обектът не беше изтрит, той оставаше в паметта.
Всички предложения на Чата за проверки на NULL и комбинациите им с проверки като isVisible бяха неуспешни. След като прекарах известно време във всевъзможни варианти на заявки към Чата, които ме водеха по кръг, се обърнах към Google, където успях да намеря решение.
За Bullet беше необходимо да се използва функцията на жизнения цикъл на обекта и в нея да се извика затваряне, чрез което обектът, притежаващ Bullet (Hero), ще го изтрие.
void OnBecameInvisible()
{
// Перевіряємо, чи є підписники на подію, і викликаємо її
OnBulletInvisible?.Invoke();
}
Стъпка 3 – Добавяне на „чудовища“
За да създам и анимирам чудовища, направих същите стъпки като при Bullet. Единствената разлика беше, че Bullet се създаваше от героя, а с чудовищата трябваше да се работи по подобен начин – да се създаде техен собствен обект (MonsterSpawner), който да ги „застрелва“.
Заявка – „Трябва обекти (чудовища) да летят на екрана от дясната страна и да летят по оста Х към лявата страна. Интервалът на поява на чудовищата е 2 секунди.“
Отговор – Чат ми предложи два скрипта – скрипт за чудовища (MonsterScript.cs) и скрипт за създаване на чудовища (MonsterSpawner.cs).
Запитване – „Къде да използвам скрипта MonsterSpawner? Да го прикрепя към някакъв обект?“.
Отговор – „Да, можете да прикрепите скрипта MonsterSpawner към някой обект във вашата сцена. Създайте празен обект GameObject, изберете го в йерархията и след това прикрепете скрипта MonsterSpawner към този обект. След това ще можете да конфигурирате настройките на monster spawner (напр. prefab на чудовището, интервал на поява и т.н.) чрез инспектора на Unity“
Следващото нещо, което трябваше да се направи, беше да се създаде “убийство” чудовище.
Стъпка 4 – Направете така, че чудовището да изчезне след улучване на куршума
Запитване – „Чудовищата трябва да изчезват при сблъсък с куршум.“
Отговор – „Ще трябва да добавите Box Collider 2D към чудовищата и куршума, за да откривате сблъсъци.“
Чат също така даде две актуализирани скриптове за Bullet и Monster, които отчитат сблъсък и нов скрипт за MonsterSpawner, който направи премахване на чудовище при сблъскване и задействане на clojure.
Направих подобни манипулации с куршума – сега имах сцена, която вече приличаше на нещо.
Стъпка 5 – Създаване на фонов режим с безкрайно превъртане
За фон реших да използвам принтскрийн на изображение на звездно небе. Идеята беше това изображение да се върти безкрайно и най-важното – безпроблемно по оста Х като фон на сцената.
Запитване – „Как да направя безкраен фон, който се движи от дясно на ляво?“.
Отговор – „За да създадете безкраен фон, който се движи от дясно наляво, можете да използвате два екземпляра на фона един до друг и да ги преместите, докато се движат, за да създадете ефект на безкрайност.“
Опцията с две снимки не ме устройваше.
Запитване – „Трябва да създам безкраен фон от една снимка“
Отговор – „За да създадете безкраен фон от една снимка в Unity, можете да използвате скрипт, който ще премести фоновата текстура по хоризонталната ос, създавайки ефект на безкрайност.“
Фонът не се движеше. Чатът се опита да ми даде различни съвети за конфигуриране на компонентите, но сякаш просто ми ги предлагаше по кръг.
Тогава се опитах да превключа на английски език, тъй като прочетох, че Чатът го разбира по-добре и дава по-точни отговори. Резултатът не се промени – продължавахме да се въртим в кръг.
След като загубих доста време, се обърнах към Google и намерих решението там. За фона на безкрайността беше необходимо да създам обект от съвсем различен тип – Quad, да създам материал за него въз основа на моята снимка и да настроя текстурен шейдър за него по определен начин.
След всичко това вероятно е останало още едно нещо:
Запитване – „Как да направя така, че куршумите да не се припокриват с фона?“
Отговор – „За да направите така, че куршумите да не се припокриват с фона, можете да използвате системата от слоеве в Unity. Уверете се, че фонът и куршумите се намират на различни слоеве, и регулирайте реда на слоевете им, така че фонът да е под куршумите.“
Затова промених Z-йерархията на слоевете и всичко проработи. Остават само изображенията.
Стъпка 6 – Добавяне на снимки за всички обекти
Не ми трябваше Чат, за да добавям снимки към всеки обект. Вече знаех това от урока. Получих желаният резултат, като създадох спрайтове с всяка картинка и ги прикрепих към желаните обекти.
Заключения
- Чатът наистина ускорява процеса на разработка, като предлага готови скриптове по заявка и обикновено ги придружава с инструкции – как и какъв обект да добавите и персонализирате.
- Качеството на отговорите пряко зависи от качеството на запитванията – колкото по-прецизно е запитването с подробности и нюанси, толкова по-вероятно е отговорът на Chat да сработи от първия път
- За някои проблеми, които Чатът не можеше да реши, трябваше сами да потърсим решение – мемори ликове, правилна работа на безкрайните фонове, изборът на подходящи шейдъри
- За създаването на мини игри са ви необходими умения за работа с Unity
- Струва ми се, че Chat може да спести 20-30% от времето за разработка. За всеки тип игра ви е необходимо разбиране за това как всичко трябва да си взаимодейства и какви нюанси съществуват за различните случаи.
- Колкото по-умело работите с Unity, толкова по-ефективно можете да работите с Chat
- Отговорът от Чата ще бъде по-пълен, ако заявката е направена ясно и изчерпателно. Бих искал да спомена, че по време на експеримента беше използвана безплатната версия 3.5. Очевидно е, че резултатите от платената версия ще бъдат по-добри.
Автор Александър Бондар