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

Хотя в игры, которые я создавал, не стоило играть, опыт написания собственного кода что-то пробудил во мне. Я понял, что даже ребенок может управлять компьютерами, заставлять их делать то, что я хочу… Я научился программировать.

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

Разработка игр отличается

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

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

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

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

Охватывая двигатель

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

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

Представьте, что вы обучаете новичка-младшего программиста своему ремеслу. Если вы веб-разработчик, что бы вы порекомендовали им сделать в первую очередь? Создать их «фейсбук, но лучший клон»? Или настроить простую пробную страницу, используя выбранную вами структуру?

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

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

Перемещение вещей

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

То же самое и с физикой..

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

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

Петля — это видно! (как бы)

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

Однако когда вы перейдете к разработке игр, вы заметите, что цикл виден (или почти виден). В Unity движок вызывает методы для каждого игрового объекта, который активен в вашей сцене, без вашего указания.

Эти методы вызываются в разное время, и вам нужно знать, как их использовать. Например, метод Awake() вызывается в начале жизненного цикла объектов и часто используется для кэширования ссылок на другие объекты и инициализации состояния.

Метод Update() вызывается в каждом кадре и является обычным местом для кода движения и обработки ввода.

Но не думайте, что вы будете выполнять проверку коллизий в Update. На самом деле, возвращаясь к использованию движка, коллизии отправляются вам более насыщенным способом с использованием таких методов, как OnCollisionEnter, OnCollisionStay, OnTriggerEnter , и т.д.

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

Чтобы узнать немного больше об этих методах в Unity, взгляните на страницу Execution Order здесь. У него есть красивая диаграмма, показывающая методы и время их вызова: https://docs.unity3d.com/Manual/ExecutionOrder.html.

Частота кадров имеет значение

Конечно, все мы знаем, что частота кадров в наших играх важна. Если он падает слишком низко, игра чувствует себя плохо. Но это также влияет на то, как работает наш код.

Это связано с тем, что такие методы, как Update(), вызываются в каждом кадре. Итак, если ваша игра работает со скоростью 10 кадров в секунду, обновление вызывается 10 раз в секунду. Если он работает со скоростью 300 кадров в секунду, вы будете вызывать обновление 300 раз в секунду.

Почему это важно? Потому что ваш код должен это учитывать. Если вы перемещаете объект по оси X на 1 единицу при каждом обновлении, скорость будет варьироваться в зависимости от частоты кадров. При 10 кадрах в секунду он будет двигаться на 10 единиц в секунду, при 300 кадрах в секунду он будет двигаться намного дальше.

Опять же, есть простое решение этой проблемы в статическом плавающем элементе Time.deltaTime, к которому вы можете получить доступ. Умножение вашего количества движения на это сгладит все на основе вашей текущей частоты кадров… но вы должны знать, что она существует, чтобы использовать ее.

Настройка проекта

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

В Unity установка полностью основана на структуре папок, а код — это лишь малая часть вашего проекта. Помните, что это важно, код — это лишь крошечная часть вашего проекта!

И метод запуска вашего проекта? Недействительный основной ()? Вы этого не увидите. Для ваших целей его не существует.

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

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

Это не в коде… но это в вашей сцене. Ваша сцена — это место, где вы настраиваете эти вещи.

Часто опытные разработчики узнают об этом и сразу же создают сцену «настройки» с одним файлом кода и методом setup/main, который строит свою игру. Не делайте этого...

Именно так выглядит борьба с движком. Сцены существуют не просто так, чтобы сделать разработку игры чистой и быстрой. Выстраивание всего в коде усложняет сборку, отладку, расширение и завершение… без каких-либо преимуществ, кроме приятного ощущения замены main() или App_Start(). Сцены существуют, чтобы помочь вам, и научиться правильно их использовать жизненно важно для достижения успеха.

Как насчет зависимостей и инъекций?

В прошлом я писал посты о DI в Unity. После небольшого периода веб-разработки моя любовь к DI возродилась, и я снова поэкспериментировал с созданием проекта Unity с DI.

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

Есть несколько фреймворков, которые делают DI для Unity, но они не получают должного внимания… и на это есть веская причина… они также борются с движком. Они делают именно то, что я только что сказал не делать, они создают игру в коде, а не в сцене.

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

Но как мне настроить свои зависимости?

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

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

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

Что насчет компонентов?

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

Разработчики C#. Стоит отметить, что методы моноповедения во многом похожи на переопределенные виртуальные методы, но на момент написания этой статьи они больше напоминали «магические» именованные методы, поскольку в них отсутствует ключевое слово override. Однако для ваших целей просто представьте, что перед ними есть ключевое слово override.

Каждый игровой объект в Unity содержит как минимум 1 компонент, называемый преобразованием. Преобразование обрабатывает положение, поворот и масштаб.

Чтобы создать работающую вещь в своей игре, вы будете комбинировать различные компоненты.

Например, если бы вы создавали монету, которую игрок мог бы схватить, у вас было бы преобразование, коллайдер сфер, аниматор (чтобы заставить ее вращаться) и собственный скрипт для обработки удара и потребления монеты.

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

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

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

Некоторые навыки, которые хорошо переводятся (и дадут вам преимущество)

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

ТВЕРДЫЙ — Если вы сторонник твердых принципов, они могут быть очень полезными. Я бы особенно сосредоточился на принципе единой ответственности. Я видел бесчисленное количество опытных разработчиков игр, которые делают удивительные вещи, но с трудом понимают и используют преимущества принципа единой ответственности. Помните об этом, когда вы создаете свои компоненты, пусть они будут небольшими, многоразовыми и заменяемыми.

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

И, конечно, ваш общий опыт программирования полезен. А знание .net framework — огромное подспорье для Unity.

Следующий

Я еще многое хочу осветить... различия в тестировании, графике, рендеринге, ресурсах, звуке, управлении сценами, управлении проектами и многом другом...

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

Поэтому, если вам интересно, как применить некоторые навыки в разработке игр, спросите об этом.

Первоначально опубликовано на сайте unity3d.college 26 июля 2017 г.