Вещи, которые я бы хотел знать до начала разработки собственной игры

Original author: Spajus
  • Translation


Последние два года я в свободное от основной работы время разрабатывал личный проект — игру, которую выпустил в Steam пару месяцев назад. На протяжении всего процесса я делал много ошибок, и вел записи для своего «прошлого я». Этот список может не относиться ни к вашей игре в частности, ни к вашему движку или языку (я использовал Unity и C#). Но я верю, что кому-то эти советы могут помочь. Поехали.

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

  • Сделать сложную и отполированную игру, которую можно выпустить и даже иметь небольшой шанс на успех, будет в 100 раз сложнее, чем вы можете представить. Я не преувеличиваю.
  • Используйте правильную шкалу единиц с самого начала, особенно если у вас есть физика в игре. В Unity, 1 единица = 1 метр. Неправильный масштаб сделает вашу физику странной.
  • Спрайты должны быть сделаны и импортированы с согласованным размером, DPI, PPU.
  • Убедитесь, что спрайты — это POT. Либо упакуйте их в атласы.
  • Включите кранч сжатие на всех спрайтах, где можете (POT + кранч может легко превратить 1,3 Мб в 20 Кб)
  • Создайте UI из компонентов, которые можно реюзать.
  • Последовательно назовите UI-компоненты, чтобы их было легко найти.
  • Сделайте гайд по стилю игры на ранних этапах.
  • Используйте пространства имен на C# и разбивайте свой код на ассемблеры на ранних этапах. Это обеспечивает более чистое разделение архитектуры и сокращает время компиляции в долгосрочной перспективе.
  • Никогда не используйте magic strings или string constants. Если вы печатаете строки в сериализованных полях Unity Editor, которые позже будут где-то использоваться для идентификатора — остановитесь. Используйте перечисления.
  • Выделите большие непрерывные сеансы на свою игру. 2 цельных часа гораздо продуктивнее, чем 4 раза по 30 минут.
  • Дизайн не должен быть частью прототипа. Не пытайтесь сделать его красивым, вам все равно придется его выбросить.
  • Не тратьте время на создание арта (если, конечно, это не ваша основная цель). Если вы знаете, что он все равно будет выглядеть дерьмово, как бы вы ни старались, то сосредоточьтесь на том, что вы умеете лучше. Позже вы научитесь арту, или найдете коллегу в команду, кто сделает это за вас.
  • Избегайте public static в C#.
  • Попробуйте делать меньше ООП. Держите все в изоляции, имейте меньше состояний. Обменивайтесь данными, а не объектами с состояниями и иерархиями.
  • Избегайте больших классов и методов любой ценой. Разделите обязанности, и cделайте это на ранних этапах. 300 строк, скорее всего, слишком много для класса, 30 строк, безусловно, слишком много для одного метода.
  • Организуйте арт также, как вы организовываете код. Он должен быть четко и логически разделен, иметь пространство имен и правила по неймингу.
  • Не просто копируйте и слегка модифицируйте код из других ваших игр — создайте общую библиотеку вещей, которые могут быть использованы позже.
  • Если вы используете ScriptableObjects, они могут быть легко сериализованы в JSON. Это полезно для включения моддинга.
  • Подумайте о моддинге на ранней стадии. Разложите начальную архитектуру проекта так, чтобы вы могли построить ядро игры в виде мода или набора модов. Игровой контент должен быть «мягкой» архитектурой, он должен легко модифицироваться.
  • Если вы планируете сделать онлайн-мультиплеер — внедряйте его с 1--го дня. В зависимости от типа игры и вашего кода, добавление мультиплеера поверх готового проекта будет варьироваться от сверхтяжелого до почти невозможного.
  • Не давайте ранние незавершенные версии игры стримерам и инфлюенсерам. Иначе эти геймплейные видео еще долго будут вас преследовать.
  • Растите сообщество в Discord и Reddit.
  • Сделайте сборки для всех ОС (Win, Linux, Mac).
  • Прекратите тестировать игру после каждого изменения или давать сборки с ошибками вашему сообществу. Напишите в Unity плэймод-тесты игры и тесты интеграции: они могут играть в вашу игру на 100-кратной скорости и находить ошибки.
  • Назовите свои GameObjects также, как вы называете свои классы MonoBehaviour. Или сделайте последовательные названия, чтобы было проще их искать. Да, вы можете использовать поиск, но хорошо названная иерархия игровых объектов намного лучше.
  • Постройте надежную систему UI заранее, а затем используйте ее для построения всей игры. Сделать гибкий пользовательский интерфейс очень сложно.
  • Никогда не подключайте кнопки пользовательского интерфейса к редактору Unity Editor. Вместо этого используйте onClick.AddListener из кода.
  • Постарайтесь определить как можно больше в коде, а не полагаться на Unity Editor или предварительную сериализацию. Когда вам понадобится что-то рефакторить, наличие множества вещей, соединенных в единые YAML-файлы, добавит вам проблем. Используйте редактор, чтобы быстро найти хороший набор значений в рантайме, затем впишите его в код и удалите [SerializeField].
  • Не используйте публичные переменные. Если вам нужно выставить частную переменную в Unity Editor, используйте [SerializeField].
  • Будьте последовательны в именования и организации кода.
  • Не срезайте углы и не идите на компромиссы по самым важным и сложным частям игры — основной механике, процедурной генерации, управлению и т.д. Вы пожалеете об этом позже. Под «срезанием углов» я имею в виду неаккуратное обращение с кодом, многократное копирование-вставка некоторых вещей, написание длинного метода с большим количеством if заявлений и т.д. Все это будет очень мешать при рефакторинге.
  • Хорошо подумайте над финальным названием игры. Переименование позже может превратиться в полный кошмар.
  • Назовите ваш проект кодовым именем. Не начинайте с именования, покупки доменов, настройки аккаунтов, покупки приложения Steam и т.д. Это можно сделать намного позже.
  • При выполнении процедурной генерации, визуализируйте каждый шаг процесса, чтобы понять и проверить его. Если вы будете делать предположения, то ошибки все испортят. А отладка без визуализации станет кошмаром.
  • Установить шрифты TextMeshPro по умолчанию.
  • Не используйте iTween. Используйте LeanTween или другое производительное решение.
  • Избегайте 2D физики Unity даже для 2D-игр. Постройте ее с 3D, и вы получите многопотоковый Nvidia Physx вместо менее производительного Box2D.
  • Используйте Debug.Break() для перехвата странных состояний и их анализа. Очень хорошо работает в сочетании с тестами.
  • Делайте сборки как можно быстрее. Инвестируйте время, чтобы понять, где у сборок узкие места — сэкономите больше в долгосрочной перспективе. Например, вам не нужно компилировать 32К шейдерных варианта на каждой сборке. Используйте предварительно загруженные шейдеры, чтобы получить значительное ускорение (Edit > Project Settings > Graphics > Shader Loading).
  • Сделайте все элементы пользовательского интерфейса префабами.
  • Избегайте LayoutGroup и всего, что вызывает восстановление Canvas, особенно в методе Update, и особенно если вы планируете перенести игру на консоли.
  • Начните разработку игру с последней бета-версией Unity. К тому времени, как вы закончите, эта бета-версия будет стабильной и устаревшей.
  • Ассеты из Asset Store следует называть Liabilities. Чем меньше вы используете, тем меньше у вас будет проблем.
  • Используйте Unity Crash Reporting. Вам не придется просить людей присылать логи. Спросите их ОС, видеокарту, и найдите отчеты о сбоях с логами в онлайн панели управления.
  • Повышайте версию приложения каждый раз, когда делаете сборку. Это должно быть сделано автоматически. Очень полезно в сочетании с Unity Crash Reporting — вы будете знать, если новые сборки получат старые проблемы. А когда что-то приходит со старой версии, вы будете знать, что это не платные пользователи, а пират со старой копией игры.
  • Очаровательный динамический UI не стоит того. Сделайте пользовательский интерфейс простым и удобным. Никогда не используйте диагональные компоновки, если не хотите пройти через мир боли.
  • Если вы строите игру, в которой ИИ будет использовать вход на основе PID-контроллера (виртуальный джойстик), сначала разберитесь с обработкой и управлением — и только потом начните работать с ИИ. Иначе придется переписывать его каждый раз.
  • Используйте редактор кода, который показывает ссылки на классы, переменные и методы. Например, Visual Studio Code — он великолепен.
  • Множество примеров кода, которые можно найти в интернете, абсолютно ужасны. Его можно переписать, чтобы он был намного короче и/или более производительным. Например, Steamworks.NET.
  • Непринятые исключения внутри корутинов Unity приводят к крашам, которые невозможно отладить. Все, что работает в корутине, должно быть абсолютно пуленепробиваемым. Разделите корутины на подметоды, обработайте там исключения.
  • Постройте систему управления корутиной. Вы должны знать, какие корутины работают в настоящее время, как долго, и т.д.
  • Сделайте фотомод на ранней стадии. После этого вы легко будете делать красивые скриншоты и материалы для трейлеров.
  • Постройте себе консоль разработчика. Пробовать что-либо быстро и без необходимости строить UI — это фантастика. А игроки смогут использовать консоль для модификации/читов и т.д.
  • Не полагайтесь на PlayerPrefs. Сериализуйте вашу игровой конфиг со всеми настройками в простой текстовый формат.
  • Никогда не тестируйте более 1 изменения за раз.
  • Не вставайте в 4 утра, чтобы поработать над игрой. Не кранчите, отдыхайте и делайте физические упражнения. Хорошо питайтесь (максимизируйте потребление белка, избегайте углеводов и жиров — это худшее). Не убивайте себя, чтобы сделать игру.
  • Если вы не знаменитость с >10К фанатов, то спам об игре в Твиттере будет бесполезен. Хэштег #gamedev движется со скоростью несколько сообщений в секунду — скорее всего никого не будет волновать ни ваша игра, ни то, что вы недавно сделали. Лучше займитесь разработкой.
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 24

    +2
    Используйте пространства имен на C# и разбивайте свой код на ассемблеры на ранних этапах. Это обеспечивает более чистое разделение архитектуры и сокращает время компиляции в долгосрочной перспективе.
    А можно в числах? А то везде про это пишут, но я в своих проектах не вижу прям большой разницы при использовании Assembly Definitions.
    Напишите в Unity плэймод-тесты игры и тесты интеграции
    Вот про это бы поподробнее.
    Начните разработку игру с последней бета-версией Unity
    Очень спорный совет.
    Не полагайтесь на PlayerPrefs. Сериализуйте вашу игровой конфиг со всеми настройками в простой текстовый формат.
    А что не так с PlayerPrefs?
    Если вы не знаменитость с >10К фанатов, то спам об игре в Твиттере будет бесполезен. Хэштег #gamedev движется со скоростью несколько сообщений в секунду — скорее всего никого не будет волновать ни ваша игра, ни то, что вы недавно сделали
    #screenshotsaturday для некоторых весьма хорошо работает.
      0
      А что не так с PlayerPrefs?

      Размер? Удобство редактирования?
        –1
        Размер?
        Оно точно также хранит в текстовом формате.
        Удобство редактирования?
        В редакторе? Там много лет назад был удобный плагин для этого. Или можно самому за несколько часов накидать.
          0
          Оно точно также хранит в текстовом формате.

          Почитайте про лимит на хранение данных в префсах.
            –2
            Если вы упираетесь в лимиты PlayerPrefs, то это не проблема PlayerPrefs, вы его просто не по назначению используете.
              –2
              хранение конфигурации — не есть назначение PlayerPrefs. Настройки звука, графики может — да. Но речь шла про игровой конфиг.
        0
        А можно в числах? А то везде про это пишут, но я в своих проектах не вижу прям большой разницы при использовании Assembly Definitions.

        Зависит от того насколько качественно разбили. Юнитеки пишут (емнип), что вы либо используете асмдефы по всему проекту, либо не используете вообще. В любом случае, важно понимать, что если вы меняете код в сборке, которую используют все остальные — пересобираться будут все, а не только она.
          –2
          Везде прописаны и для всех плагинов. И вот особой разницы не заметил =/
        +21
        разбивайте свой код на ассемблеры

        Assembly в .Net переводится как сборка.
          +3
          Попробуйте делать меньше ООП. Держите все в изоляции, имейте меньше состояний. Обменивайтесь данными, а не объектами с состояниями и иерархиями.

          Странный совет. Я бы наоборот, сказал, что делая игру — делайте больше ООП, потому что объектно-ориентированное моделирование (ECS или нет — это уже детали) обычно на игры ложится прекрасно.
          Но важно помнить, что абстракции ООП не бесплатны, и вот тут-то как раз речь идёт о том, о чем в статье: не надо плодить тучи временных объектов, тут мигом можно убить и память и производительность (когда GC офигеет) разом.
            +1
            Возможно имелся в виду component-based design. ООП в чистом виде можно использовать толко на уровне подсистем. Как не надо делать: класс типа Car с методами update/move/shoot (конечно же перегружаемыми для каждого под-класса). Смерть для производительности и потом очень сложно такое выкорчевать.
              0

              А как надо?

              +4

              Думаю, что тут про принцип "composition over inheritance"

              0
              Мне кажется, имеется в виду событийная система. Она не отрицает ООП, а по сути — является даже её более идеальным представителем, но самое главное — позволяет избавится от знания объектов о том, какие ещё объекты есть в коде. Учитывая, что в юнити зависимостей порождается ещё больше чем в любом другом коде(из за перелинковок со сценой и контроллерами, например), без системы сообщений у меня любой рефакторинг вызывал боль, поскольку приходилось менять поведение по цепочке в целой куче объектов.
                –2
                ООП это самое большое зло для игр на Unity.
                Там другая парадигма.
                Совсем.
                И чем быстрее забудете это аббревиатуру — тем быстрее сможете что-то сделать)))
                +3
                Согласен с большинством советов, но некоторые моменты спорные:
                Постарайтесь определить как можно больше в коде, а не полагаться на Unity Editor или предварительную сериализацию. Когда вам понадобится что-то рефакторить, наличие множества вещей, соединенных в единые YAML-файлы, добавит вам проблем. Используйте редактор, чтобы быстро найти хороший набор значений в рантайме, затем впишите его в код и удалите [SerializeField].

                Автор предалагает хардкодить какие-то значения, которые можно задать в эдиторе? Или выность в какие-то отдельные файлы настроек? А ссылки как — через GetComponent<>? )

                Избегайте 2D физики Unity даже для 2D-игр. Постройте ее с 3D, и вы получите многопотоковый Nvidia Physx вместо менее производительного Box2D.

                Если проект для мобил — сдается мне, что 2D будет все таки профитнее. Хотя лучше проверить и убедиться.

                Используйте редактор кода, который показывает ссылки на классы, переменные и методы. Например, Visual Studio Code — он великолепен.

                Попробуй Rider — он еще великолепнее. )
                  0
                  ну кстати для своего проекта в целом хороший прогресс (я про выводы), хотя некоторые конечно очень спорные )
                    0
                    Мне показалось противоречивым:
                    • Хорошо подумайте над финальным названием игры. Переименование позже может превратиться в полный кошмар.
                    • Назовите ваш проект кодовым именем. Не начинайте с именования, покупки доменов, настройки аккаунтов, покупки приложения Steam и т.д. Это можно сделать намного позже.

                    К тому моменту как займёшься именованием, покупкой доменов, настройкой аккаунтов и т.п, внезапно что-то запланированное тобой уже может быть занято, см. предыдущий пункт.
                      –1
                      Я думал что с юнити игры делать проще, но сейчас вижу, что даже для 2д гонок нашлась целая куча проблем.
                        0
                        Неплохой набор моментов о которых стоит задуматься :)
                        Некоторые оч спорные это да, кажется некоторые хорошо ложатся на одиночную разработку и не подходят для студии :)
                        такие как этот:
                        Постарайтесь определить как можно больше в коде, а не полагаться на Unity Editor или предварительную сериализацию. Когда вам понадобится что-то рефакторить, наличие множества вещей, соединенных в единые YAML-файлы, добавит вам проблем. Используйте редактор, чтобы быстро найти хороший набор значений в рантайме, затем впишите его в код и удалите [SerializeField].


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


                        Хотелось бы узнать у автора какая боль ему встретилась что он такое предлагает:
                        Никогда не подключайте кнопки пользовательского интерфейса к редактору Unity Editor. Вместо этого используйте onClick.AddListener из кода.

                        Я например тут полностью несогласен. Тут сильно лучше встроить какой нить MVVM фреймворк, если нету своего, и никогда не не делать код зависимым от UI. Только UI зависимый от кода.
                          –1
                          Имеется в виду не делать вызов методов через инспектор кнопки (там же можно перетянуть ссылку на монобех в специальное поле на кнопке, и указать какой метод вызвать и с какими параметрами). Вот так лучше не делать, как минимум потому, что потом программистам сложно отследить откуда идут вызовы, да и вообще зависимости строить сильно сложнее.
                            0
                            Я понимаю :)

                            И именно про это и сказал. MVVM как раз за то чтобы именно так и делать (настраивать вызов в инспекторе) и не иметь зависимости кода от UI. Только контролируемо.

                            Стандартный инспектор юнити не дает никакого контроля и да лучше его не использовать.
                            У на для этого свой компонент который делает это верно (с нашей точки зрения :))
                            он дает вызывать только методы которые явно в коде отмечены аттрибутом [Callable]

                            Программисты явно выдают методы для вызова из UI и код не зависит от того есть там кнопка в том UI или нет и вообще где она и сколько их. И может то вообще не кнопка а чекбокс который вызывает метод на включении… то уже дело UI.
                              –1
                              ясно. Ну да, возможно. Мы больше придерживаемся MVC и вью подписывается на ивенты кнопки, а снаружи у нее торчат уже свои ивенты, на которые подписывается контроллер. В рамках этого чтобы задействовать инспектор пришлось бы делать контроллер монобехом, ну и снова — теряли бы возможность отследить связи

                        Only users with full accounts can post comments. Log in, please.