Как сделать раннер на unity

Разработка игр на Unity 3D — бесплатные видеоуроки для детей и подростков

Короткие последовательные уроки по Unity 3D подойдут как для начинающих детей, так и для более продвинутых разработчиков.

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

Unity (Юнити) — популярный современный движок для создания 2D- и 3D-игр. На нем были разработаны такие известные проекты, как Hearthstone, Pokemon Go, Kerbal Space Program и другие. На Unity можно создавать как компьютерные игры, так и игры на смартфон. Для написания скриптов в нем используется язык программирования С# (Си Шарп).

Дети и подростки тоже могут начать создавать несложные игры на Unity. Школа программирования для детей «Пиксель» делится короткими последовательными видеоуроками, которые познакомят детей с разработкой игр на Юнити. Благодаря этим урокам вы сможете начать обучение Unity с нуля и освоите азы программирования на Си Шарп. А еще создадите свои первые проекты и научитесь «собирать» их под Android или ПК и загружать в Play Market. Давайте начнем?

Урок 0. Установка Unity

Для начала давайте скачаем и установим Unity на ПК.

Урок 1. Создание анимации в Unity 2D

Начнем изучение Юнити с анимации персонажа. В первом видеоуроке мы покажем, как добавить спрайт на сцену и запрограммировать его так, чтобы он двигался с нужной скоростью. Напишем первый скрипт на языке программирования C#.

Урок 2. Как создать телепорт в Unity

В этом уроке мы разберем, как добавить в наши игры телепорт. Мы возьмем два куба и расположим их в разных частях сцены. При касании одного куба наш персонаж будет тут же перемещаться к другому, напишем для этого скрипт телепорта на Си Шарп.

Урок 3. Спавн объектов в Unity

Спавн — важная составляющая любой игры, место, где появляются наши объекты при запуске игры. Мы разберем 2 способа добавления спавна: на canvas и в пределах камеры.

Урок 4. Триггеры в Unity 3D

Триггеры нужны в играх, чтобы собирать бонусы или наносить урон персонажам. В этом видео покажем, как запрограммировать сбор очков и столкновение персонажей в Юнити.

Урок 5. Как создать таймер в Unity

Таймер — еще одна важная часть почти каждой игры. Мы научимся добавлять таймер в Юнити двумя способами: используя корутину или команду InvokeRepeating.

Урок 6. Перемещение объекта мышью в Юнити

Мы научим вас добавлять в игры функцию Mouse Drag. Это метод перетаскивания объектов в игре с помощью компьютерной мыши. В видео мы показали, как он может использоваться: например, для того чтобы перенести еду на питомца и накормить его.

Урок 7. Полоса здоровья персонажа

В этом видео мы покажем, как добавить Health bar (полосу жизни) в ваши игры. Она будет увеличиваться или уменьшаться в зависимости от ваших успехов в ходе игры.

Урок 8. Сохранение игры в Unity

Прошли несколько уровней и заработали много очков, а теперь хотите сохраниться? Мы покажем, как добавить сохранение игры с помощью метода PlayerPrefs.

Урок 9. Как сделать «Раннер» в Unity за 30 минут

Мы создадим «Раннер» с динозавром — тот самый, в который Google предлагает нам сыграть, если веб-страница перестает грузиться. В этом уроке мы повторим пройденное: вновь сделаем анимацию, добавим препятствия (триггеры), спавн и полосу жизни.

Урок 10. Как экспортировать игру из Unity на ПК или Андроид

В этом видео вы узнаете, как установить нужные настройки в Unity, чтобы собрать игру под ПК или Android.

Урок 11. Как загрузить игру из Unity в Play Market

Хотите поделиться своей игрой с другими пользователями и начать на ней зарабатывать? Мы покажем, какие настройки нужны для того, чтобы подготовить игру и загрузить ее в Play Market.

Урок 12. Как сделать прыжок в Unity 2D и 3D

Мы покажем, как научить персонажа прыгать в 2D- и 3D-игре на Unity. Для этого нам понадобится создать две сцены и написать скрипты на Си Шарп.

Урок 13. Как сделать управление персонажем в Unity 2D и 3D

Мы расскажем, как научить персонажа двигаться в 2D- и 3D-играх на Unity. Для этого нам нужно изучить переменные типа float — они нужны для скорости, поворотов и других перемещений персонажа.

Урок 14. LineRenderer в Unity

В этом видеоуроке мы изучим рендер линий в Юнити. LineRenderer — это метод, который упрощает рисование линий в игре. Мы создадим два скрипта с разными функциями.

Урок 15. Как создать автосимулятор в Unity

Давайте сделаем гонки в Юнити! Мы расположим трассу, настроим автомобиль и напишем скрипты для коробки передач. Поехали!

Урок 16. Terrain в Unity

Мы покажем, как добавить инструмент Террейн в Юнити и пользоваться им. Он позволит создавать разнообразный ландшафт на сцене.

Урок 17. Диалоги в Unity

Диалоги в играх важны для продвижения сюжета. Именно через диалоги герои рассказывают игроку, какие события произошли и что ему нужно сделать. А еще в диалоговом окне нам могут дать подсказку. В этом видео мы покажем, как сделать диалоги в Юнити.

Урок 18. Как сделать NPC в Unity

NPC (Non-Player Character) — это неигровой персонаж, который находится под управлением не игрока, а специальной программы. NPC может общаться с игроком, давать подсказки или просто вливаться в общий фон игры. Давайте добавим НПС в Юнити.

Урок 19. Как сделать инвентарь в Unity

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

Урок 20. Как создать «Шутер» в Unity за 30 минут

Урок 21. Как создать Flappy Bird на Unity

Помните веселую мобильную игру с птичкой? Она лавировала между трубами, стараясь остаться в полете как можно дольше. Мы покажем, как создать ее на Unity 2D.

Урок 22. Как сделать выбор персонажа в Unity

Хотите играть за Железного человека или Капитана Америку? Из этого видео вы узнаете, как добавить возможность выбора персонажа в ваши игры.

Урок 23. Как сделать магазин в Unity

Материал подготовлен школой программирования для детей «Пиксель». Мы учим детей 5-17 лет программировать, создавать игры и анимацию и другое. Приходите к нам на полный курс по разработке игр в Unity, если хотите прокачаться в геймдеве и научиться создавать крутые игры.

Источник

Мобильная 3D игра на Unity3D менее чем за 90 часов

Этап-1: концепция

Как правило, начинающие разработчики, наступают на свои первые и самые значимые грабли уже на данном этапе, потому что перед тем, как приступить к созданию чего-либо, неплохо было бы оценить собственные возможности. Просто задайте себе вопрос: хватит ли у вас сил, времени и умений на создание проекта ААА класса? Ответ – нет! Отбросьте эту идею в долгий ящик, и не возвращайтесь к ней до тех пор, пока не реализуете чертову дюжину удачных проектов. К слову, под удачей мы подразумеваем количество установок от 500 тысяч, рейтинг свыше 3,5 по 5-ти бальной шкале и коммерческий успех. Для начала, займитесь более простыми, я бы даже сказал приземленными проектами, вроде аркад в стиле addictive games, сочетающих в себе все необходимые нами критерии «удачного» проекта.

Преимущества стиля addictive games:

Этап-2: создание наброска

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

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

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

Этап-3: создание прототипа

Имея под рукой подробный план действий, можно смело приступать к созданию «мокапа» или прототипа будущей игры. По сути, данный этап – начало работы с Unity, и начинать его следует с настройки окружения. Вот, как это настроено у меня:

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

В левой части экрана расположились редактор Scene и Game. Последний отображает то, как именно игра выглядит на устройствах. В правой части: панели Hierarchy и Inspector, а чуть ниже расположены панели Project и Console.

Этап-3.1: под капотом

Внимание! Ниже будет описан простейший код реализации игры, рассчитанный на новичков, и демонстрирующий то, насколько быстро и просто можно добиться результата в Unity. Финальный код игры реализован на более глубоких познаниях языка, включающий проблемы хранения данных, оптимизации и монетизации проекта, однако, по понятным причинам, в данной статье о них говориться не будет. Все скрипты мы будем писать на C#, а тем, кому это не интересно, предлагаю смело переходить к Этапу-4: визуальный дизайн

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

Итак, сцена готова, но как придать персонажу движение? Для начала, произведем некоторые манипуляции с объектом Sphere, добавив в него такие компоненты как Rigidbody и только что созданный скрипт sphereBehavior. Не забудьте отключить галочку Use Gravity, так как на данном этапе он нам не понадобится.

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

Если вкратце, то компонент Rigidbody позволяет объекту ощутить на себе все прелести физического мира, таких как масса, гравитация, сила тяжести, ускорение и.т.д. Вот почему для нас он так важен! А теперь, чтобы заставить тело двигаться в нужном нам направлении, нам всего лишь нужно слегка изменить параметр velocity, но делать это мы будем при помощи кода. Давайте заставим сферу двигаться по оси Х, для этого внесём изменения в скрипт sphereBehavior:

В Unity, тела описывают своё положение и направление, посредством специальных векторов, хранящих значения по осям x, y и z. Изменяя эти значения, мы добиваемся необходимого нам направления или положения конкретного тела. Строка rb.velocity = new Vector3(speed, 0f,0f) задает новое направление телу по оси X, тем самым придавая нашей сфере нужное нам направление.

Если вы сделали всё в точности, как и я, то ваша сфера отправится в бесконечное путешествие по оси X, со скоростью speed.

Теперь давайте заставим нашу сферу изменять свое направление, при каждом клике левой клавиши мыши так, как это реализовано в игре ZIGZAG. Для этого мы вновь вернемся к коду sphereBehavior и изменим его следующим образом:

Условимся, что когда сфера движется по оси X, то это движение называется движением «вправо», а по оси Z – «влево». Таким образом мы легко можем описать направление нашего тела специальной булевой переменной isMovingRight.

Этот кусочек кода отслеживает нажатие левой клавиши мыши, и если данная клавиша все же была нажата, запускает функцию changeDirection(), с простой логикой: если на момент нажатия левой клавиши мыши, переменная isMovingRight имела значение true, то теперь она стала false и наоборот. Напомню, что булевая переменная позволяет нам ответить на один простой вопрос: истинно ли утверждение о том, что тело движется по оси X, или нет? Иными словами, нажатие на левую клавишу мыши постоянно изменяет значение isMovingRight, то на true(тело движется вправо), то на false(тело движется влево).

Альтернативно, функцию changeDirection() можно записать в одну строку:

И последнее, что необходимо сделать, это переписать метод направления движения с учетом переменной isMovingRight:

Если isMovingRight имеет значение true (если сфера действительно движется вправо), тогда значение velocity принимает новый вектор направления rb.velocity = new Vector3 (speed, 0f, 0f); Если isMovingRight имеет значение false, значит тело более не движется вправо, а значит пришло время изменить вектор направления на rb.velocity = new Vector3 (0f, 0f, speed);

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

Круто? Конечно нет! Ведь сфера движется, а мы стоим на месте. Давайте доработаем игру так, чтобы мы могли двигаться вместе со сферой и не упускали её из виду. Для этого нам нужно создать скрипт cameraFollow и прикрепить его к объекту Main Camera:

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

А вот код скрипта cameraFollow:

Как же осуществить слежение за объектом? Для начала нам нужно рассчитать разницу смещения между объектами Camera и Sphere. Для этого достаточно вычесть от позиции камеры, координаты сферы, а полученную разницу сохранить в переменной offset. Но прежде, необходимо получить доступ к координатам сферы. Для этого нам необходима переменная player, представляющая собой простой GameObject. Так как наша сфера находится в постоянном движении, мы должны синхронизировать координаты камеры с координатами сферы, приплюсовав полученное ранее смещение. Осталось только указать в поле player наш объект слежения, и можно смело любоваться результатом. Просто перетащите объект Sphere в поле Player, скрипта cameraFollow, как это показано на картинке (Main Camera при этом должна оставаться выделенной):

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

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

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

Если в вашем списке нет тэга Ground, то его необходимо создать во вкладке Add Tag.

Следующее, что нам предстоит совершить, это создать в корне проекта специальную папку с названием Prefabs, и перетащить в нее наш Cube, прямо из инспектора. Если после этого, имя объекта Cube стало синего цвета, значит вы все сделали правильно.

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

Префабы – это особый тип объектов, позволяющий хранить GameObject, а также все его значения и свойства в одном месте. Префабы позволяют создавать бесконечное множество объекта, а любое его изменение немедленно отражаются на всех его копиях. Иными словами, теперь мы можем вызывать участок пути Cube, прямо из папки Prefabs, столько раз, сколько необходимо.

Теперь давайте создадим пустой GameObject, (щелчок правой кнопки мыши по Hierarchy) переименуем его в RoadContainer и прикрепим к нему только что созданный скрипт roadBehavior:

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

А вот и сам код roadBehavior:

Что же тут на самом деле происходит? Как видите, у нас есть переменная, которая позже, вручную будет привязана к нашему префабу Cube, и есть объект Vector3, хранящий координаты последнего установленного префаба (сейчас значения равны нулю).

Этот участок кода выполняет следующее: до тех пор, пока i

Источник

Реализация и оптимизация генератора уровней в Unity

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

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

Интеграция генерации карт в движок Unity

Мы будем писать Scriptable Objects движка Unity для создания модульного окружения в целях генерации карт. Таким образом, мы дадим гейм-дизайнерам свободу настройки входных данных алгоритма без необходимости работы с кодом. Если вы ещё не слышали о ScriptableObjects, то рекомендую для начала изучить документацию Unity.

Сначала нам потребуется набор различных контейнеров данных. Наш конвейер довольно сложен, и если поместить все необходимые параметры в один объект, он окажется слишком объёмным. Поэтому мы будем использовать по одному пакету данных на каждый уровень алгоритма.

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

Итак, карта составляется из одного или нескольких сегментов (slice), состоящих из одного или нескольких фрагментов (chunk), созданных из одной или нескольких текстур. Примечание: в большинстве алгоритмов этап сегментов пропускается, но я включил этот этап для дизайна конкретной игры и генерации путей; о причинах я расскажу в этой статье. Можно без проблем игнорировать сегменты и всё равно реализовать описанное здесь решение. При помощи очень удобного ExtendedScriptableObjectDrawer Тома Кэйла мы можем расширить настройки для простоты редактирования.

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

Здесь вы видите, какой тип данных и на каком уровне мы упаковываем. По сути, каждая генерируемая нами текстура будет распределять один ассет карты. Поэтому чтобы получить разнообразное распределение ассетов, нам нужно наложить друг на друга множество текстур. Разбиение карты на фрагменты и сегменты позволяет нам изменять генерируемые ассеты в соответствии с расстоянием от точки начала координат.

Каждый уровень данных имеет связанный с ним класс C#, использующий паттерн «фабрика», который мы применяем для выполнения логики каждого этапа. Если бы мы хотели только распределять ассеты, то этапы генерации были бы очень простыми. Однако нам также нужно создать пути, по которым будет двигаться игрок. Это немного усложняет архитектуру, потому что после генерации точек нам нужно соединить фрагменты и сегменты.

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

Генератор картКак сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

Генератор сегментовКак сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

Генератор фрагментов

Если не учитывать пока генерацию путей, то единственная логика, которая нам сейчас нужна — это преобразование сгенерированных на текстуре точек в мировое пространство. Это реализуется благодаря использованию параметра масштабирования из параметров карты, что обеспечивает нам удобный контроль над плотностью размещения ассетов.

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

scale = 25Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

scale = 50Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

Поскольку мы сохранили кажду точку в мировом пространстве со связанным с ней префабом, для расположения ассетов достаточно просто вызвать Instantiate для префаба, ссылка на который указана в соответствующем слое параметров фрагмента. Единственное, что нужно учитывать — наш алгоритм не гарантирует, что ассеты не наложатся друг на друга. Пока мы применим такое решение: дадим каждому префабу коллайдер и будем уничтожать все ассеты, с которыми пересекаемся при создании экземпляра префаба. Как сказано в нашем предыдущем девлоге, нужно вызвать Physics2D.SyncTransforms() и yield return new WaitForFixedUpdate(), чтобы проверки коллизий работали правильно.

Вот и всё! Нам удалось преобразовать наш эксперимент на Processing в работающую систему на движке Unity! Но, увы…

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

Ускоряем работу

Мы улучшили наш алгоритм, распараллелив его. Так как мы генерируем набор независимых друг от друга текстур (но зависящих от лежащего в их основе шума Перлина), то можно распараллелить генерацию текстур в каждом фрагменте и даже распараллелить генерацию фрагментов.

В официальной документации C# написано, что async / await являются базовой функциональностью C#. Хотя я хорошо знаком с другими возможностями. перечисленными на этом сайте, до начала проекта я не использовал ни async, ни Tasks. Основная причина заключается в том, что в Unity есть похожая функциональность. И это… (барабанная дробь) корутины. На самом деле, в руководствах по программированию на C# в качестве примера используется стандартный способ применения корутин (выполнение запроса к серверу). Это объясняет, почему я (и многие другие Unity-разработчики, которых я знаю) пока не использовал пока асинхронное программирование на C#. Однако это очень полезная возможность и мы используем её, чтобы распараллелить генерацию карт.

Вот краткое введение в асинхронное программирование. Как и в случае с корутинами, при реализации асинхронного метода нам нужно возвращать особый тип (Task). Кроме того, нужно пометить метод ключевым словом async. Затем можно использовать ключевое слово await таким же образом, каким бы мы использовали оператор yield в корутине.

Однако существует также очень удобный метод Task.WhenAll, который создаёт Task, блокирующий исполнение, пока не будет завершён набор задач. Это позволяет нам реализовать следующее:

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

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

Источник

Борьба с 2D-физикой в Unity на примере бесконечной игры

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

Мой странный творческий путь занес меня в разработку игр. Благодаря отличной студенческой программе от IT-компании, название которой СостоИт из одной Греческой МАленькой буквы, сотрудничающей с нашим университетом, удалось собрать команду, родить документацию и наладить Agile разработку игры под присмотром высококлассного QA-инженера (здравствуйте, Анна!)

Без особо долгих размышлений, в качестве движка был выбран Unity. Это замечательный движок, на котором действительно быстро и легко можно сделать очень плохую игру, в которую, в здравом уме, никто и никогда не будет играть. Чтобы создать хорошую игру, все же придется перелопатить документацию, вникнуть в некоторые особенности и набраться опыта разработки.

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

Проблема 1: Бесконечность

Unity хранит и обрабатывает координаты объектов в виде обычных 32-битных float, имеющих точность где-то до 6 знака после запятой. Проблема в том, что игра у нас бесконечная и, если мы достаточно долго будем лететь, начнутся различного рода безумные баги, вплоть до телепортации сквозь стены. Есть несколько подходов к решению этой проблемы:

Проблема 2: Генерация уровня

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

Есть несколько основных подходов к строительству endless runner’ов:

Структура уровня

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

Летим мы в пещере, она имеет пол и потолок — пару блоков, элементарных строительных единиц. Блоки объединяются в сегменты, которые бесшовно стыкуются друг с другом. Сегменты, как единое целое, вращаются вокруг самолета и двигаются по его вектору скорости, создавая иллюзию полета. Если сегмент выходит из поля зрения камеры — он очищается от блоков, пристыковывается к последнему сегменту уровня и заполняется новыми блоками, согласно указаниям генератора. Совокупность таких сегментов — и есть уровень.

Опытные Unity-разработчики могли вполне оправданно поморщиться, прикинув объем работ и все возможные подводные камни. Но на словах все просто, а опыта разработки у меня не было…

Основные Законы Физики в Unity

За месяц разработки, экспериментов и чтения документации, я выделил три основных закона физики в Unity. Их можно нарушать, но плата за нарушение — производительность. Движок никак не будет предупреждать вас о допущенной ошибке, а без профайлера вы можете никогда о них и не узнать. Несоблюдение этих законов может замедлить вашу игру в десятки раз. Как я понял, нарушение любого закона приводит к тому, что физический движок помечает коллайдер-нарушитель как некорректный и пересоздает его на объекте, с последующим пересчетом физики:

1. Коллайдеры не должны двигаться, вращаться, включаться\выключаться и менять размер.

Как только вы добавили коллайдер на объект — забудьте про какое-либо воздействие на него или объекты, в которых он содержится. Обычный коллайдер — исключительно статический объект. Дерево, например, может быть с одним коллайдером. Если дерево может упасть на игрока — дерево будет падать вместе с производительностью. Если это дерево растет из волшебного питательного облака, которое коллайдера не имеет, но может перемещаться — это будет сопровождаться падением производительности.

2. Если объект движется или вращается — он должен быть твердым телом т.е. иметь компонент Rigidbody.

Про это написано в документации, да. Которую не обязательно вдумчиво читать, чтобы начать делать игру, потому Unity очень прост и интуитивно понятен.
Rigidbody меняют отношение физического движка к объекту. На него начинают воздействовать внешние силы, он может иметь линейную и угловую скорости, а самое главное — твердое тело может двигаться и вращаться средствами физического движка, не вызывая полный пересчет физики.
Существует два типа твердых тел — обычные и кинематические. Обычные тела взаимодействуют друг с другом и обычными коллайдерами — одно тело не может пройти сквозь другое. Кинематические тела следуют упрощенным правилам симуляции — на них не воздействуют никакие внешние силы, гравитация — в том числе. Они свободно могут проходить друг через друга и коллайдеры, а вот обычные твердые тела они отталкивают, как будто имея бесконечную массу.
Если объекты не жалко отдать под контроль физического движка — используйте обычные твердые тела. Например, если вам нужно красиво скатить камни со скалы. Если ваши скрипты или аниматоры управляют объектом напрямую — используйте кинематические тела, так вам не придется постоянно бороться с движком и случайными столкновениями объектов. Например, если у вас анимированный персонаж или управляемая ракета, взрывающаяся при контакте с чем-то.

3. Если объект является твердым телом — двигаться и вращаться он должен через методы твердого тела.
Есть три уровня управления твердым телом:

— Самый высокий и, следовательно, естественный, уровень — через силы. Это методы AddForce и AddTorque. Физический движок учтет массу тела и правильно посчитает результирующую скорость. Все взаимодействия тел происходят на этом уровне.
— Средний уровень — изменение скоростей. Это свойства velocity и angularVelocity. На их основе вычисляются силы, влияющие на тела при их взаимодействии, а также, очевидно, их положения в следующий момент времени. Если у твердого тела очень маленькая скорость — оно «засыпает», для экономии ресурсов.
— Самый низкий уровень — непосредственно координаты объекта и его ориентация в пространстве. Это методы MovePosition и MoveRotation. На следующей итерации вычисления физики (это важно, поскольку каждый последующий вызов метода в рамках одного кадра заменяет вызов предыдущего) они выполняют телепортацию объекта в новое положение, после которой он живет как раньше. В нашей игре используется именно этот уровень, и только он, потому что он предоставляет полный контроль над объектом.

Что остается за бортом? Включение\выключение объекта и масштаб. Я не знаю, есть ли способ изменить размер объекта, не смущая движок. Вполне возможно, что нет. Выключение объекта проходит безболезненно, а включение… да, вызывает пересчет физики, в окрестностях включенного объекта. Поэтому старайтесь не включать одновременно слишком много объектов, растяните этот процесс во времени, чтобы пользователь не заметил.

Есть закон, не влияющий на производительность, но влияющий на работоспособность: твердое тело не может быть частью твердого тела. Родительский объект будет доминировать, поэтому ребенок будет или стоять на месте относительно родителя, или вести себя непредсказуемо и неправильно.

Есть еще одна особенность Unity, не относящаяся к физике, но достойная упоминания: динамическое создание и удаление объектов через методы Instantiate/Destroy — БЕЗУМНО медленный процесс. Я боюсь себе даже представить, что там происходит под капотом во время создания объекта. Если вам нужно создавать и удалять что-то динамически — используйте фабрики и заправляйте их нужными объектами во время загрузки игры. Instantiate должен вызываться в крайнем случае — если у фабрики вдруг закончились свободные объекты, а про Destroy забудьте навсегда — все созданное должно использоваться повторно.

Применение законов на практике

(в этом разделе находится ход рассуждений при создании игры и ее особенности)

Как сделать раннер на unity. Смотреть фото Как сделать раннер на unity. Смотреть картинку Как сделать раннер на unity. Картинка про Как сделать раннер на unity. Фото Как сделать раннер на unity

Скрипт на оси получает данные с гироскопа и выставляет ей соответствующий угол… И нарушает сразу множество правил, потому что вращение передастся по иерархии на коллайдеры, что сведет физический движок с ума. Придется делать ось твердым телом и вращать ее через соответствующий метод. Но что с движением уровня? Очевидно, что ось вращения и объект уровня перемещаться не будут, каждый сегмент нужно двигать персонально, иначе мы сталкиваемся с проблемой бесконечности. Значит, твердыми телами должны быть сегменты. Но у нас уже есть твердое тело выше в иерархии и твердое тело не может быть частью твердого тела. Логичная и элегантная иерархия не подходит, все придется делать руками — и вращение, и перемещение, без использования объекта для оси вращения. Будьте готовы к такому, если у вас уникальные геймплейные фичи.

Если двигать непосредственно сегменты пришлось бы и так, то вращать их придется вынужденно. Основная сложность в том, что в физическом движке Unity нет метода «вращать объект вокруг произвольной точки» (он есть у Transform, но не искушайтесь). Есть только «вращать вокруг своего центра». Это логично, потому что вращение вокруг произвольной оси — одновременно и вращение, и движение, а это две разные операции. Но его можно имитировать. Сначала вращаем сегмент вокруг своей оси, потом вращаем координаты «своей оси» вокруг самолета. Благодаря тому, что самолет у нас в начале координат, не придется вспоминать даже школьную геометрию и лезть в википедию, в Unity уже все есть. Достаточно перевести угол поворота в кватернион и умножить его на координаты точки. Кстати, узнал я об этом прямо во время написания статьи, до этого использовалась матрица поворота.

В конечном итоге, настоящие координаты сегмента, каждый кадр, вычисляются центром управления движением уровня как-то так:

После всех вычислений и костылей, необходимых для работы точной стыковки сегментов при регенерации, segment.truePosition отправляется в метод MovePosition твердого тела сегмента.

Выводы

Насколько все это быстро работает? На старых флагманах — Nexus 5 и LG G2 — игра летает на 60 FPS, с еле заметной просадкой во время включения новых коллайдеров во время генерации сегмента (это неизбежно и никак не обходится) и выдвигания червяков из земли (можно нагородить какой-то ад, чтобы это обойти, но сейчас там осознанное нарушение третьего закона). 40 стабильных FPS выдает любое устройство с гироскопом, которое нам попадалось. Без знания и учета всех законов, производительность была, мягко сказать, неудовлетворительной и телефоны перегревались. Настолько, что я думал написать свой простенький специализированный движок для 2д-физики. К счастью, физика в Unity оказалось достаточно гибкой, чтобы все проблемы можно было обойти и создать уникальную игру, достаточно было лишь пары недель экспериментов.

Теперь, зная все главные подводные камни физического движка Unity, вы сможете быстро склонировать нашу игру, разрушив мечты, жизни и веру трех бедных студентов в человечество. Я надеюсь, эта статья сэкономит вам много времени в будущем и поможет найти не совсем очевидные нарушения законов производительной физики в своих проектах.

Читайте документацию и экспериментируйте, даже если пользуетесь простыми и интуитивно понятными инструментами.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *