Как я делал руку с картами для своей карточной игры

Зона, с которой игрок чаще всего взаимодействует в карточной игре — это его рука (не путать с рукой в играх с 18+ контентом). Рука — это набор карт, которые игрок может разыграть в текущий ход. И раз это одно из самых важных мест, я решил уже на этапе прототипа сделать руку приятной и красивой.

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

Вот как раз во время работы с рукой (не путать с «во время работы рукой») я понял отличие качественной игры от поделки на уровне прототипа для тестирования геймплея. Все дело в мелочах и деталях. Посмотрите, как ведут себя карты в руке в Slay the Spire:

Как я делал руку с картами для своей карточной игры Gamedev, Инди, Инди игра, Unity, Разработка, ККИ, Гифка, Видео, YouTube, Длиннопост

Теперь посмотрите на те же карты на видосе у чела, который пишет в названии ролика, что он сделал Slay the Spire за неделю (9:11):

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

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

Как я делал руку с картами

Первую руку я сделал по туториалу, с которого делал первый прототип. В нём за формирование руки отвечал компонент Grid, который расставляет объекты по сетке. Grid лишает вас необходимости писать код, который отвечает за расстановку карт: вы просто задаете настройки и карты сами встают ровно при любом количестве, когда попадают в нужный родительский объект.

Как я делал руку с картами для своей карточной игры Gamedev, Инди, Инди игра, Unity, Разработка, ККИ, Гифка, Видео, YouTube, Длиннопост

Интерфейс компонента: как видите, все отступы, расположение и расстояния можно настроить тут, не нужно писать код

Проблема с Grid была в том, что делалось это некрасиво: карты телепортировались в сетку, а мне хотелось, чтобы они плавно переходили.

Недолго погуглив, я нашёл в Ассет Сторе бесплатный ассет Smooth Grid. Там были желанные плавные переходы. Если я вытаскивал карту, она потом вставала в конец — ну да и ладно, решил я.

Как я делал руку с картами для своей карточной игры Gamedev, Инди, Инди игра, Unity, Разработка, ККИ, Гифка, Видео, YouTube, Длиннопост

В настройках все то же самое, только еще есть плавность: насколько быстро карты переходят в свое место в сетке

Проблемы со Smooth Grid появились, когда я решил сделать руку похожей на руку в реальной жизни и в других карточных играх — чтобы карты слегка наезжали друг на друга — и после этого стал думать, как мне сделать выделение карты по наведению курсора. Сначала карты просто не хотели выезжать. Когда я разобрался с выездом, понял, что карта не хочет выходить на передний план. Всплыла проблема с тем, что эта плавная сетка перемещала карты влево или вправо в зависимости от положения объекта с картой в инспекторе. А значит, если я буду выводить карту на передний план с помощью перемещения в инспекторе, карта будет перескакивать со своей позиции в самую крайнюю в руке. Такое мне точно не подходило.

Как я делал руку с картами для своей карточной игры Gamedev, Инди, Инди игра, Unity, Разработка, ККИ, Гифка, Видео, YouTube, Длиннопост

Я понял, что в 2D в Unity не было способов перетащить объект на задний и передний план кроме свойства Sorting Layer. Вот только применить его можно только к объектам с компонентом Sprite Renderer. Он отвечает, например, за то, чтобы у карточки выводилась нужная картинка. А у меня все объекты имели компонент Image — я выводил изображение карточки с помощью него.

Так вот, чтобы выводить карточку на передний план, мне нужно было менять компонент Image на компонент Sprite. И это привело к своим сюрпризам. Оказывается, все объекты внутри Canvas с компонентом Image будут перекрывать любой другой объект. И когда я создаю объект Background, который задумывал как фон, он перекрывает спрайты карточек, и поверх фона ничего не видно. И это довольно логично: любой объект внутри Canvas Unity распознает как часть интерфейса: а интерфейс как бы должен быть поверх всего остального в игре. Но…на осознание этих правил у меня ушло много времени. А еще много времени на то, чтобы разобраться, как выставить настройки у спрайтов, поправить поехавшую камеру и сделать кучу мелких действий.

Следующее открытие: Event Trigger, компонент, с помощью которого я делал выведение карточек на передний план при наведении мыши и разыгрывании карточек, не хотел работать со спрайтами. Один и тот же скрипт у меня работал на объекте с Image и переставал работать на объекте со Sprite Renderer. Оказалось, есть еще один способ регистрировать наведение мышки: с помощью методов MouseEnter, MouseExit и MouseOver.

Дальше меня ждали новые проблемы. Я использовал метод Lerp, чтобы карточки красиво залетали в руку и красиво выдвигались, когда наводишь на них курсор. Все отлично работало ровно до тех пор, пока я не совмещал анимации карточек с их добавлением в Smooth Grid. Тогда начиналась котовасия.

Как я делал руку с картами для своей карточной игры Gamedev, Инди, Инди игра, Unity, Разработка, ККИ, Гифка, Видео, YouTube, Длиннопост

Дело в том, что Smooth Grid тоже построен на Lerp. А Lerp — это такая функция, которая как резиночка тянет объект на родительское место. И вот проблема была в том, что Lerp в сетке и мой Lerp спорили между собой, а карточки в итоге трясло и кидало в разные стороны. Я пытался это решить попеременным отключением Lerp’ов — не сработало. Все начинало ехать еще больше.

В итоге пришлось отказаться от компонента Grid совсем: и от Smooth, и от обычного. Я сам сделал простенький вывод на нужную позицию с помощью цикла for, максимально костыльно.

Как я делал руку с картами для своей карточной игры Gamedev, Инди, Инди игра, Unity, Разработка, ККИ, Гифка, Видео, YouTube, Длиннопост

Смотрю и даже стыдно смотреть...

Вот что у меня получилось в итоге

Как я делал руку с картами для своей карточной игры Gamedev, Инди, Инди игра, Unity, Разработка, ККИ, Гифка, Видео, YouTube, Длиннопост

Скорее всего, прокатит для трейлера. Но для реальной игры нужно будет править, чтобы, например, карточки выравнивались по центру и расстояние между ними менялось, когда карточек в ряду становится больше или меньше. А еще наведение курсора не всегда регистрируется, и при желании порядок выдачи и улетания карт в сброс можно сломать.

Что думаю про сишарп

Несмотря на кучу проблем, мне нравится работать с сишарпом. Но по сравнению со всякими JS и Python синтаксис у него выглядит более избыточным:

Как я делал руку с картами для своей карточной игры Gamedev, Инди, Инди игра, Unity, Разработка, ККИ, Гифка, Видео, YouTube, Длиннопост

Не напоминает ли это вам этот момент из «Кролика ДжоДжо» (0:18):

Хотелось бы конечно сделать так же сочно, как в Slay the Spire, но это капец сколько ещё ковыряться. Вообще при разработке стараюсь максимально отсекать всё лишнее. Например, когда я понял сейчас, что надо много всего перепиливать, я отсек вообще всю логику, которая не нужна была для той задачи, которую я поставил себе здесь, в телеге. Этим путём я следую и при разработке части игры для трейлера: максимальный говнокод (даже по моим меркам, а я тот ещё программист), максимум бутафорских штук. Например, у меня карточки тупо вылазят из края экрана, а там они изначально лежат перед запуском экрана.

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

***

Этот пост входит в цикл постов про игру, которую я потихоньку делаю уже несколько месяцев. Я делюсь всем производственным процессом: какие решения я принимаю в разработке, геймдизайне, интерфейсе, арте и других сферах. В моем телеграм-канале вы можете посмотреть другие посты и узнать, когда ждать следующие: @nigylamchan.

Лига Разработчиков Видеоигр

6.8K постов22.2K подписчика

Добавить пост

Правила сообщества

ОБЩИЕ ПРАВИЛА:

- Уважайте чужой труд и используйте конструктивную критику

- Не занимайтесь саморекламой, пишите качественные и интересные посты

- Никакой политики


СТОИТ ПУБЛИКОВАТЬ:

- Посты о Вашей игре с историей её разработки и описанием полученного опыта

- Обучающие материалы, туториалы

- Интервью с опытными разработчиками

- Анонсы бесплатных мероприятий для разработчиков и истории их посещения;
- Ваши работы, если Вы художник/композитор и хотите поделиться ими на безвозмездной основе

НЕ СТОИТ ПУБЛИКОВАТЬ:

- Посты, содержащие только вопрос или просьбу помочь
- Посты, содержащие только идею игры

- Посты, единственная цель которых - набор команды для разработки игры

- Посты, не относящиеся к тематике сообщества

Подобные посты по решению администрации могут быть перемещены из сообщества в общую ленту.

ЗАПРЕЩЕНО:

- Публиковать бессодержательные посты с рекламой Вашего проекта (см. следующий пункт), а также все прочие посты, содержащие рекламу/рекламные интеграции

- Выдавать чужой труд за свой

Подобные посты будут перемещены из сообщества в общую ленту, а их авторы по решению администрации могут быть внесены в игнор-лист сообщества.


О РАЗМЕЩЕНИИ ССЫЛОК:

Ссылка на сторонний ресурс, связанный с игрой, допускается только при следующих условиях:

- Пост должен быть содержательным и интересным для пользователей, нести пользу для сообщества

- Ссылка должна размещаться непосредственно в начале или конце поста и только один раз

- Cсылка размещается в формате: "Страница игры в Steam: URL"