Гайд: Как создать кликер на Unity
Я являюсь преподавателем в школе программирования ЯЮниор и не так давно мы опубликовали пост с разбором жанра кликеров и пообещали, что если пост наберет 100 плюсов, то жаба разрешит мне выпустить статью по разработке кликера! Мы видим, что тема вам интересна, и не можем просто так оставить это без внимания.
Разработка кликера
Сегодня мы с вами пошагово разработаем кликер, суть которого заключается в создании тортиков. Это будет не просто счетчик кликов, а полноценный кликер с выпеканием тортов, магазином и всеми вытекающими.
Спрайты для урока:
Создаем торт
Начнем мы с вами с главного, с торта. Торт у нас будет собираться послойно, у каждого слоя будет цена — сколько кликов нужно сделать, чтобы собрать определенный слой.
Торты у нас будут заранее созданы и храниться в префабах. Чтобы сделать первый торт — создайте на сцене пустой объект и назовите его Cake. После этого создайте папку Prefabs в окне Asset, а в ней Cakes. Перетащите с окна Hierarchy созданный пустой объект торта в папку Cakes.
2 раза кликаем по получившемуся префабу, и переходим в режим редактирования префаба. Сразу проверьте, чтобы координаты родительского объекта были нулевыми.
Размещаем слой торта, и устанавливаем размер по Y 1.5
После этого дочерним к слою располагаем крем и выставляем ему Scale 1 по всем осям. После установки, раскрашиваем слой и крем.
Первый уровень торта готов, но хотелось бы сделать его минимум из 3 уровней. Выделяем слой, и нажимаем ctrl+d, мы получили дубликат слоя, сдвигаем его повыше, и видим следующую картину:
Тут проблема в слоях. Вам нужно вручную проставить Order in layer для каждого спрайта в торте. Получается, что у нашего 1 уровня будет слой 0, а у крема 1. Далее всё зависит от того, сколько вам нужно будет уровней для торта, но каждый последующий слой будет больше.
В итоге у нас получится вот такой торт. Хотел бы обратить внимание на пару вещей.
Как вы можете заметить, у некоторых слоев торта крем идет отраженный по x оси, это сделано для того, чтобы торт смотрелся более живым. Это делается при помощи установки чекбокса тут:
Также для упрощения понимания, приведу структуру полученного торта и какие слои у каждого элемента.
Как вы видите, у нас есть 3 коржа. У каждого коржа есть крем, а у последнего ещё и конфети. Распределение слоев идет следующим образом:
- корж 1 — слой 0;
- крем 1 — слой 1;
- корж 2 — слой 2;
- крем 2 — слой 3;
- корж 3 — слой 4;
- крем 3 — слой 5;
- все конфети — слой 6.
Теперь наш торт окончательно готов, и т.к. пустой GameObject торта находился на сцене, то сейчас там появится целый торт.
Добавляем фон
Фон мы с вами расположим на Canvas, для этого нажимаем правой кнопкой мыши по окну иерархии и создаем Canvas.
Canvas нужен для отрисовки графического интерфейса, но также на нем можно расположить и фон. Перед работой нам нужно его настроить.
Первым делом переключаем Render Mode в Camera и указываем камеру, к которой будет привязан канвас, т.к. у нас она одна, то её и указываем.
После этого нам нужно указать настройки для адаптивности нашего интерфейса, для этого в Scale Mode выбираем Scale With Screen Size. Этот режим означает, что мы разработаем весь интерфейс для определенного эталонного разрешения, а дальше unity будет его растягивать отталкиваясь от этого. Указываем Reference Resolution 1080 на 1920 и Match 0.5, mathc — это то, как будет тянуться интерфейс, по ширине или по высота, в случае с 0.5, это по ширине и высоте одновременно.
Канвас настроен, теперь нажимаем пкм по канвасу в окне иерархии, и создаем объект Panel, он будет являться нашим фоном, указываем в Source Image картинку нашего заднего фона. Теперь фон указан, но он какой-то темный, чтобы убрать это затемнение, вам следует нажать лкм на color и параметр A(alpha) установить в 255. Теперь ваш фон смотрится адекватно.
После этого настройте положение и размер торта так, чтобы он ровно вставал на подставку, у вас должна получиться следующая картина:
Создаем место для торта
Наши торты не будут изначально стоять на платформе, да и много разных их будет, по этому нам нужно с вами настроить место для спавна тортов.
Создаем пустой объект, и называем его CakePlace. Размещаем его на платформе так, чтобы он обозначал нижнюю точку торта.
Как вы можете заметить по скрину выше, пивот нашего торта находится не у его основания, а это значит, что когда мы будем создавать торт из скрипта, то он будет выглядеть именно так, как на скрине, а это не ровно. Чтобы исправить это, нам нужно поднять все слои чуть вверх, для этого переходим в редактирование префаба, выделяем все слои, и чуть приподнимаем вверх.
Как вы можете заметить, пивот стал ниже, а это значит, что при спауне торт встанет хорошо.
Теперь, наконец-то, перейдем к скриптам)
Создаем папку для скриптов, и в неё уже создаем скрипт CakePlace.
Пока наш скрипт будет выглядеть так, мы будем постепенно его дописывать. Давайте разберем, что он делает сейчас. У нас есть поле торт, в котором будет храниться тот торт, который мы хотим заспаунить. В старте мы вызываем метод SetCake, который просто создает торт дочерним к нам. Также уже готов метод RemoveCake, который будет удалять торт.
Этот компонент мы добавляем к объекту CakePlace. Удаляем со сцены сам торт и в поле Cake указываем префаб нашего торта.
Теперь при запуске игры вы увидите, что торт создался внутри CakePlace. На этом этапе торт уже должен стоять ровно, если это не так, то снова перейдите в редактирование префаба и приподнимите или опустите слои.
Скрипты торта
В папке скрипты создаем папку Cake, а в ней 2 скрипта: Cake и CakeLayer.
CakeLayer
У нас есть следующие поля:
- _clicksBeforeCooking — сколько кликов нужно, чтобы слой был готов;
- _spriteRenderer — хранит компонент отрисовки этого слоя;
- _layerColor — цвет нашего слоя поле выпекания;
- CookingProgress — свойство, которое обозначает прогресс, сколько кликов уже сделано.
Зачем нам хранить цвет слоя? Дело в том, что нам надо как-то помечать то, что слой не выпечен, и пользователь видел, что он сейчас выпекает. Для этого мы каждый слой в старте превращаем в призрачный — белый слой с небольшой прозрачностью.
Как торт выпекается?
Каждый раз при клике, прогресс будет увеличиваться. Когда прогресс достигнет нужного количества кликов для выпекания, тогда цвет заменится на нормальный, а метод вернет true.
Этот компонент нам нужно добавить на каждый элемент торта.
Cake
Начнем разбор с полей:
- _profit — прибыль которую мы получим за выпекание торта;
- _layers — все наши слои;
- _createdLayers — сколько слоев уже создано;
- Done — свойство, которое возвращает результат сравнения выпеченных слоев и общего количества.
На старте мы получаем с наших детей все компоненты CakeLayer, чтобы мы могли контролировать послойное выпекание.
OnClick будет вызываться каждый раз при кликах по экрану.
Если торт не готов, то мы вызываем метод TryBakeLayer, который пытается испечь слой. В нем мы получаем текущий слой и вызываем у него увеличение прогресса, после чего пытаемся его завершить (этот if можно было заменить на return cakeLayer.TryCookLayer();).
После чего снова происходит проверка на то, готов ли торт.
Также после 42 строки добавьте следующую строку:
_createdLayers++;
Это нужно, чтобы мы перешли к приготовлению следующего слоя
Настройка торта
Теперь нужно закинуть эти компоненты на торт.
На основной объект помещаем компонент Cake, а на все слои помещаем компонент CakeLayer
Покликовое создание торта
Основной частью кликера является считывание кликов. Считывать клики мы с вами будем по панельке канваса.
Нажимаем пкм по канвасу и создаем Panel. Он сразу будет серым, нажимаем Color и A уводим в 0.
Также сейчас наша зона кликов находится под фоном, а значит клики до неё не дойдут, тут вам следует убрать галочку Raycast Target с фона
Скрипт Clicker Zone
Мы наследуем наш компонент от интерфейса IPointerClickHandler, который позволяет нам определять клики по нашей панели. Также у нас есть событие клик, которое мы пробуждаем во время клика по нашей панели.
Получается такая схема: клик по панели -> пробуждение события -> все, кто подписаны, выполняют определенное действие.
Этот компонент мы добавляем на наш пустой объект ClickerZone.
Модифицируем скрипт CakePlace
Мы добавили поле ClickerZone, чтобы иметь возможность подписать наш торт на событие о клике, а также добавили подписку торта на клики при создании, и отписку при удалении.
Мы добавили поле, не забудьте указать в него ClickerZone.
Теперь мы можем покликово собирать тор!
Сбор тортов и зачисление очков на баланс
Создаем в папке скриптов папку Player, а в ней скрипты Player и PlayerWallet
Тут в целом все просто, у нас методы на пополнение и списание, а также приватное поле и свойство которое его раскрывает
А игрок просто содержит кошель.
Эти компоненты можно разместить на камере или создать пустой объект Player на сцене.
Теперь нужно собрать панельку, на которую будет кликать игрок для сбора торта. Для этого кликаем пкм по канвасу и создаем панель. Эту панель сужаем до небольшого окна, добавляем на неё текст и кнопку, чтобы итоговый результат выглядел следующим образом:
Также чтобы мы могли скрывать и показывать сразу всю группу элементов(панель, текст и кнопку) на родительский объект CakeCollector следует добавить CanvasGroup, он позволяет контролировать сразу всех детей.
Эту панельку теперь надо вызвать тогда, когда будет готов торт. Для этого нам нужно обновить пару скриптов.
Обновляем скрипт Cake
Тут мы просто добавляем событие, которое пробуждаем в момент когда торт готов.
Обновляем скрипт CakePlace
Подписываем на событие о том, что торт готов и также создаем событие о том, что торт готов к сбору. Заметьте, что событие готовности к сборке также передает с собой что это за торт, чтобы мы знали его цену.
Cкрипт CakeCollector
Теперь создаем папку UI в скриптах и добавляем скрипт CakeCollector.
Получаем торт по событию и сразу открываем панель, после чего ожидаем сбора, а потом закрываем.
Дополняем скрипт Player
Просто подписываемся на событие о сборе и добавляем столько денег, сколько приносит торт.
Теперь у нас готов сбор тортиков
Отображение баланса
Первым делом создаем панель на канвасе, указываем показанное выше изображение и добавляем текст.
Далее мы создаем скрипт WalletDisplay и добавляем событие в PlayerWallet.
Обновляем PlayerWallet
Просто добавляем событие о том, что деньги обновились
WalletDisplay
Тут мы подписываемся на обновление кошелька и обновляем данные при добавлении денег.
Теперь за торт с ценой 5 мы получили 5 валюты.
Диспенсер тортов
Сейчас торт просто появляется на сцене и после его приготовления никуда не девается. Нам пора написать раздатчик тортов, чтобы мы могли ему закинуть список возможных тортов, а он бы постоянно нам выдавал новые.
У нашего компонента есть поля:
- _cakeCollector — нужен нам для того, чтобы знать, что старый торт собран;
- _cakePlace — нужен, чтобы выдавать ему торты;
- _cakeTemplates — все доступные варианты тортов.
Мы получаем от сборщика информацию о том, что торт собран, удаляем этот торт с поля, а потом берем рандомное число от 0 до количества шаблонов и выдаем его на установку в CakePlace.
Теперь каждый раз после нажатия нам будет выдаваться новый торт.
Создание внутриигрового магазина
Первым делом создаем кнопку для магазина и размещаем в правом верхнем углу. Далее создаем скрипт ShopButton и Shop.
По нажатию на кнопку открытия (которую разместили в правом верхнем углу), мы включаем объект магазина, а при нажатии на кнопку закрытия (разместим внутри магазина) — выключаем объект.
Далее собираем магазин, создайте панель и разместите как на скрине ниже, а также добавьте кнопку закрытия.
После этого добавляем ScrollView, он нужен для расположения множества элементов.
Далее растягиваем его и создаем шаблон для товара.
Добавляем в Content шаблон Item, дублируем пару раз и добавляем компонент Horizontal Layout Group на content, это позволит ровно расположить множество элементов.
Мы разработали с вами шаблон для магазина, осталось создать товары.
Все варианты товаров мы будем хранить как SO.
Внутри SO хранятся все данные для магазина, чтобы мы могли не хранить ненужную информацию по типу самой цены или иконки внутри торта.
После этого создаем сам объект торта, который уже в свою очередь ссылается на определенный SO
Товары готовы, осталось написать только магазин, но перед этим давайте добавим в игрока метод проверки платежеспособности, чтобы знать, что у него хватает денег.
А также событие о том, что куплен новый торт, оно будет оповещать раздатчик о том, что появился новый шаблон.
Теперь приступаем к магазину
В старте мы добавляем все SO товары в магазин и подписываемся на нажатие кнопки их покупки. При покупке мы проверяем, хватает ли игроку денег и после этого передаем ему торт, отписываемся от события этого торта и помечаем его как проданный.
Шкала прогресса выпекания
Шкала прогресса слоя будет создана из простого слайдера. Нажимаем пкм по иерархии и создаем слайдер, после чего удаляем ручку из него и растягиваем части, которые не полностью заполняют его (чтобы полностью заполнить слайдер, выделите объект и слайдер value перетяните в правый край).
Также нам понадобится интересный скрипт
При обновлении прогресса, мы устанавливаем новый targetProgress и targetColor. Как вы можете заметить, Lerp применяется не для плавного перехода, а для получения промежуточного цвета.
В Update же мы просто стремимся к target значениям.
Этот прогресс осталось как-то передать, чем мы с вами и займемся.
В Cake мы создадим событие, которое будет сообщать нам о том, каков прогресс у нашего торта.
Мы добавляем ссылку на прогресс бар в CakePlace, и добавляем подписку и отписку на торт для нашего слайдера.
В целом теперь мы завершили наш кликер. Также сюда не помешает добавить эффектов, это мы как раз сделали в видеокурсе по созданию кликера, он доступен для просмотра на нашей платформе абсолютно бесплатно
Надеюсь вам понравилась эта статья, пишите в комментариях, что ещё стоит разобрать!