Разработка 2D игры на Unity (3/5) "Основы скриптинга"

Разработка 2D игры на Unity (3/5) "Основы скриптинга" Gamedev, Unity, 2D, Игры, Урок, Длиннопост, Гифка

Привет, пикабу! Вижу, данная серия оказалась не очень-то интересна, но наличие подписчиков, коих набралось уже 50 человек, обязывает закончить начатое =)
Прошу прощения за долгое отсутствие... Работа. Приходится писать ночью.

Внимание! Очень длиннопост!


Хронология постов:
Часть 1 - Знакомство с редактором.

Часть 2 - Подготовка сцены.


В этом посте мы поговорим о скриптинге в юнити. Сразу обращу внимание на три момента:
1 - Кодить мы будем на языке C#. Юнити ещё поддерживает JS, но его мы не затронем.
2 - Для знатоков. Мой код не идеален и не является истиной в последней инстанции. Тем более в этой серии. Ибо тут цель познакомить с основами, а не выдать качественную игру.
3 - Код самого приложения я буду выкладывать картинками. По двум причинам: подсветка синтаксиса и ибо нех  чтобы не копипастили. Пишите ручками, лучше запомнится.


Итак. Начнём. Давайте сразу же создадим два скрипта в уже созданной нами папке Scripts.
Для этого жмем правую кнопку мыши и в выпадающем меню выбираем Create -> С# Script.

Разработка 2D игры на Unity (3/5) "Основы скриптинга" Gamedev, Unity, 2D, Игры, Урок, Длиннопост, Гифка

Назовём их Game и Egg, так как они будут отвечать за основную логику игры и за объекты яиц, соответственно. Создали? Отлично! Для того, чтобы скрипты заработали, они должны быть помещены на какие либо объекты на сцене. Давайте создадим новый игровой объект и назовём его Zero. Как это делать, я уже писал, но вот анимашка:

Разработка 2D игры на Unity (3/5) "Основы скриптинга" Gamedev, Unity, 2D, Игры, Урок, Длиннопост, Гифка

Теперь, поместим скрипт Game на объект MainCamera, а скрипт Egg на объект Zero. Сделать это можно тремя способами: перетащив скрипт на объект в окне иерархии, перетащив скрипт к компонентам объекта в окно инспектора или нажав в инспекторе кнопку Add Component.

Разработка 2D игры на Unity (3/5) "Основы скриптинга" Gamedev, Unity, 2D, Игры, Урок, Длиннопост, Гифка

Давайте откроем скрипт Game для редактирования, дважды кликнув по нему левой клавишей мыши. Вот, что мы увидим в редакторе:

Разработка 2D игры на Unity (3/5) "Основы скриптинга" Gamedev, Unity, 2D, Игры, Урок, Длиннопост, Гифка

Как видим, Unity создала скрипт не пустым. Она подгрузила в него две стандартные библиотеки (1 и 2 строка), а так же создала публичный класс (4 строка), с тем же названием, что и имя самого скрипта, унаследовав его от базового класса MonoBehavior. Дабы сэкономить длину поста, я не буду рассказывать, зачем нужны библиотеки и базовый класс. Но стоит рассмотреть две стандартные функции, которые также создала нам Unity. 

Функция Start (7 строка) - вызывается единожды, при загрузке скрипта.

Функция Update (12 строка) - вызывается каждый раз перед обновлением кадра.


Как вы уже догадались - частота кадров в игре будет напрямую зависеть от количества расчётов, выполняемых в функции Update. Поэтому в этой функции стоит избежать таких сложных вычислений, как, например, поиск объектов на сцене. Благо, Unity позволяет присваивать "ссылки" на объекты - переменным. И это присвоение необходимо производить в функции старт, а далее - только пользоваться созданной переменной.


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

Разработка 2D игры на Unity (3/5) "Основы скриптинга" Gamedev, Unity, 2D, Игры, Урок, Длиннопост, Гифка

Итак. На седьмой строке у нас расположена переменная типа GameObject с именем zero. Она будет содержать в себе пустой игровой объект со сцены. Который будет подразумевать "сущность" яйца. То есть создавая на сцене дубликат данного объекта, мы будем иметь в виду, что на сцене появилось новое яйцо, управлять которым будет скрипт Egg. Фактически эта переменная нам не нужна и мы могли бы просто создавать новый пустой объект. Но я считаю необходимым показать на примере, как создаётся копия объекта на сцене.


Тип переменной GameObject позволяет хранить в себе ссылку на какой либо игровой объект, расположенный на сцене. Из него, вы сможете получить доступ к любому компоненту, прикреплённому к этому объекту, либо совершать операции с самим объектом.


С 10 по 13 строку мы храним игровые объекты со спрайтами положений нашего игрока.


На 15 строке мы храним числовое обозначение положения игрока.


Тип переменной int означает integer то есть целое число. Так же Unity понимает все стандартные типы данных из C# (да и остальных языков) - это float, то есть числа с плавающей запятой, string, то есть строковая переменная и bool - булевая переменная, хранящая в себе одно из двух состояний: true или false.


Далее, на 18 строке, мы видим переменную типа Transform с именем egg. Как говорит комментарий - это врЕменная переменная, необходимая только для того, чтобы мы смогли заполнить массивы с объектами наших яиц. И тут есть две интересности:


Во первых - это тип Transform, который хранит в себе информацию из компонента Transform, то есть всё, что касается положения объекта в игровом пространстве. А ещё переменная transform позволяет делать поиск по дочерним объектам. Этим его свойством мы и воспользуемся.


А во вторых, мы видим надпись [HideInInspector] строкой выше. Эта надпись говорит редактору Unity, что переменную, идущую сразу за этой надписью - необходимо скрыть из инспектора. Нужно это для того, чтобы не забивать инспектор ненужными данными и оставить только необходимые настройки.

С 21 по 28 строку, у нас располагаются массивы игровых объектов для каждого из четырёх спавнов, которые мы назвали egg1, egg2, egg3 и egg4, соответственно. Квадратные скобки после объявления типа переменной говорят именно о том, что это будет массив.


Далее расположены переменные time, count и hp (от health points). Для чего они нужны - понятно из комментариев. На этом, объявление переменных окончено.


Давайте присвоим нашим переменным объекты со сцены. Для этого идём в редактор и перетаскиваем объекты из окна иерархии в соответствующие поля в окне инспектора:

Разработка 2D игры на Unity (3/5) "Основы скриптинга" Gamedev, Unity, 2D, Игры, Урок, Длиннопост, Гифка

Отлично! Теперь наш скрипт знает, какие объекты отвечают за положение игрока, а также он знает, где расположен наш пустой объект. Но нам необходимо сделать самое главное - указать положения всех яиц на сцене. Но постойте-ка! Их же... 40 о_О И да, во первых их просто лень назначать в ручную. Во вторых - мы, вдруг, можем захотеть заменить какой либо из объектов и потом нам придётся снова назначать его в инспекторе. Давайте автоматизируем этот процесс. Займёмся инициализацией:

Разработка 2D игры на Unity (3/5) "Основы скриптинга" Gamedev, Unity, 2D, Игры, Урок, Длиннопост, Гифка

Для этого переходим к написанию функции Start.
Яйца у нас будут храниться не отдельными объектами, а целыми массивами. Так будет удобнее к ним обращаться. А для удобства заполнения этих массивов, мы создали переменную egg. Она у нас будет соответствовать компоненту трансформ, одного из расположенных на сцене спавнов. Для того, чтобы этот спавн найти, мы используем функцию Find и в скобках указываем имя искомого объекта. Всё это описано в 59-ой строке.


Далее, нам необходимо объявить массив, указав его размер (строка 61).


А после - заполняем массив, используя цикл (строка 63). 

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

В теле цикла мы присваиваем в ячейку массива, соответствующую номеру круга, гейм объект, который мы ищем среди дочерних объектов нашей временной переменной. Поиск выполняется функцией FindChild. И в скобочках нам необходимо указать имя искомого объекта. Имя у нас соответствует номеру круга. А поскольку номер круга у нас - целое число, мы конвертируем его в строку, используя функцию "ToString()".


Первый массив заполнен. Делаем всё то же самое для оставшихся спавнов.


Далее нам необходимо скрыть волка на сцене. Показывать мы его начнём только после запуска игры. Для этого просто отключаем игровой объект на сцене, перемещая флаг в функции SetActive в состояние false. Делаем то же для всех спрайтов волка (стр 81-84).


А также нам необходимо скрыть со сцены все яйца. Тут снова не обойтись без цикла...

Просто перебираем все массивы и отключаем объекты яиц уже известной нам функцией. Сие действие происходит с 87-й по 90-ю строку кода.


На этом я закончу пост. Вы можете запустить игру и убедиться в том, что яйца пропадают со сцены. Внимание!!! Для корректной работы скрипта, яйца в каждом из спавнов должны называться от 0 до 9. Целым числом. Начиная с нуля. Нет, не с единицы.


Спасибо, что дочитали и подписывайтесь, чтобы не пропустить следующие посты! ;)

DELETED
Автор поста оценил этот комментарий
Как я понял в данном контексте аттрибут HideInInspector используется вместо модмфикатора private?) Раз объект не должен быть виден ни в инспекторе, ни в других классах, используйте модификатор! А еще...лучше новичков сразу хорошему учить - общепринятому стилю написания кода на шарпе, а то научатся еще писать как на плюсах...но это так, мое ворчание:) Пост хороший, и плюс однозначно!
раскрыть ветку
1
Автор поста оценил этот комментарий

причем тут скриптинг и c#? а скриптинг на си будет?

раскрыть ветку
ещё комментарий
Автор поста оценил этот комментарий

Экхм. Инициализацию тонн объектов делать в Start? SRS?))) Awake() для слабаков?

раскрыть ветку