Здравствуйте. Не так давно у меня появилось свободное время, которое внезапно совпало со временем, когда мне захотелось сделать что-то свое, родное.
А что своего может захотеть сделать рядовой программист? Конечно же игру!
Под катом моя небольшая история, которую вряд ли можно назвать поучительной или необычайно увлекательной, но, тем не менее…
Началось все примерно неделю назад. У меня был в принципе немалый опыт программирования в целом и не было практически никакого опыта в игроделе. Где-то год-два назад я ставил себе Unity3D, дабы посмотреть что это за зверь, так что из средств разработки было выбрано единственное мне знакомое. Еще можно было бы конечно на канвасе все рисовать, но, я решил, что, пожалуй, не стоит. От этого первоначального знакомства у меня остались некие воспоминания про gameobjects, components и то, что можно сделать ортографическую камеру, чтобы делать 2D игру в Unity3D. Как оказалось, в текущих версиях юнити (начиная с 4.3) появилась поддержка 2D «из коробки», чему я несказанно обрадовался. Теперь процесс создание игрового объекта сводится к перетаскиванию спрайта на сцену. Спрайт даже скейлится под разные экраны, правда я не знаю, по ширине он это делает, высоте или вообще по площади (а может быть sqrt(площадь)?).
Здесь очень страшный и некрасивый первоначальный набросок игрового экрана.
Да, это задумывалось как платформер в стиле доисторической Impossible Game.
Нарисовано ЭТО было в порыве вдохновения, когда я вдруг решил, что мне все по силам. Показал его паре человек, снял розовые очки и начал думать. Т.к. бюджет на разработку был выделен никакой, то на роль художника/дизайнера была определена моя 12-летняя сестра.
Здесь перерисованный ей пример. Мне кажется стало лучше. А то что графика детская, так ведь игры делают для детей, да?
Итак, начался процесс разработки.
Большая ошибка раз
Первую ошибку я совершил практически сразу же, когда задумался о конструкторе уровней. После некоторых размышлений до меня дошло, что сама по себе юнити представляет собой замечательный конструктор. И вот после добавления на сцену всех нужных объектов в нужных местах, после того, как уровень был играбелен и оттестирован, я запустил это на своем неслабом nexus 5 и увидел fps порядка 5-10. Оказалось, что не было очень хорошей идеей добавить на сцену сразу все approx 400 объектов-препятствий. Так были написаны 2 скрипта, один из которых считывал все объекты, их положение и угол поворота со сцены и записывал все в текстовый файл, а второй в последствии считывал этот файл и создавал объекты на лету, когда подходило их время. Сейчас одновременно может существовать 50 объектов и нексус почувствовал себя вполне здорово, чего нельзя было сказать про jiayu g2.
Большая ошибка два
Здесь нужно заметить, с чего же началась разработка. Начал я с самого на мой взгляд простого — с динамического фона. Т.е. у нас есть 2 спрайта, которые следуют друг за другом, и когда тот который слева скрывается из виду, он переставляется вправо и бесконечный конвейер из двух спрайтов продолжает движение. И именно это стало причиной последующей грубой ошибки — я двигал не игрока относительно фона, а наоборот. Соответственно когда стали появляться новые объекты, они тоже двигались вместе с фоном, а игрок продолжал покоиться по оси Х. А тут нужно сказать спасибо вот этому списку из 46 наиболее часто встречающихся ошибок. Оказывается, что нельзя двигать collider (компонент, отслеживающий столкновения) без rigidbody (компонент, который подвержен всем законам физики; ну или не совсем всем). Т.е. в своих советах этот список доходит даже до того, что если подобные объекты создаются из кода, то нужно их сначала создать, потом переместить куда нужно и только после этого навешивать на них collider. А у меня все препятствия в игре как раз и представляют собой colliders без rigidbody. И учитывая то, что фон двигается относительно игрока… В общем, пришлось переделывать. Теперь двигаются только игрок и камера и на jiayu g2 игра тоже работает довольно плавно.
Не такая большая ошибка
Были и менее масштабные промахи. Например, учитывая вот такое расположение коллайдеров:
Из которых нижний отслеживал касание ногами земли и все хорошо, а верхний приводил к быстрой и мучительной смерти, было недопустимо, чтобы игрок проскакивал сквозь преграду и касался ее верхним коллайдером. При этом в настройках есть соответствующий чекбокс, который устанавливает continuous detection, т.е., казалось бы, как раз то что нам нужно. Но это работает только с физикой, если бы игрок прыгал и падал по физическим законам, а здесь этого допускать нельзя, т.к. в таком случае рано или поздно появятся смещения при прыжках и игрок будет падать тогда, когда он делает все правильно.
В итоге сейчас при падении запускаются 2 луча, вот таких вот:
Если один луч сталкивается с землей, а второй с шипом, то засчитывается прикосновение к земле. А финиш, например, приоритетнее земли. Так и вычисляются касания.
Звук
За музыку большое спасибо добрым людям с fma, которые распространяют ее по creative commons.
Итоги
Фух. Свободное время подходит к концу, у меня есть некоторый завершенный проект (обычно все начинания останавливаются где-то посередине). Про юнити, учитывая первоначальный багаж знаний, я теперь знаю практически в бесконечное количество раз больше, но этого все еще очень мало. Меня все еще не покидает ощущение, что все это можно было сделать куда проще и красивее.
И вот здесь, в общем-то, сама игра — тынц.
Чуть не забыл! В Android'e начиная с версии 4.4 стала доступна запись видео с экрана через adb. Так что я смог за минут 10 в мувимейкере состряпать какое-никакое видео.
P.S. Всем дочитавшим до этого места огромное спасибо!
Вам может показаться, что это маленькая поделка на несколько часов, но я потратил на нее неделю своего времени, причем вряд ли это была такая стандартная рабочая неделя, скорее это напоминало последний день перед дедлайном. Каждый день. Хотя нет, больше всего это похоже на хакатон длиною в неделю, во. В общем, поехал я на природу, восстанавливаться. Всем еще раз спасибо за внимание, я выговорился.