LG.BALUKATION's Weblog

Ничего, это тоже кое-что… А при желании из него можно сделать что угодно

Perforce для разработчиков игр

Posted by LG.BALUKATION на 2015/09/05

Существует некоторое количество систем управления версиями (revision control AKA version control AKA source control), которые хоть и преследуют похожие цели — делают при этом упор на совершенно разные штуки. Очень многие программисты отдают предпочтение такой системе под названием git и достаточно часто удивляются, когда узнают что в разработке игр популярна вовсе не она.

В разное время мне доводилось поработать с CVS, git, Perforce и Subversion и именно Perforce мне кажется наиболее подходящей для разработки игр. Многие программисты, кто занимается разработкой более классического софта, не слышали о ней или слышали очень мало — так что я немножко расскажу чем именно Perforce хорош в геймдеве.

Perforce — это коммерческий закрытый продукт, он стоит денег и поставляется без исходных кодов. Цена зависит от количества пользователей, можно сразу купить нужное число лицензий или оплачивать на них годовую подписку. Есть бесплатная версия, ограниченная 20 пользователями или 20 рабочими пространствами. Какое-то время назад продукт переименовали в Helix, но сути это не меняет.

Система это централизованная по своей идеологии, так что главными компонентами продукта являются те или иные вариации клиента и сервера. Вариациями я это назвал потому, что кроме обычного сервера (который хранит файлы и метаданные ревизий) существует ещё например прокси-сервер (кеширует файлы, а за метаданными о ревизиях ходит на обычный сервер) и не только. Так же условные «клиенты» бывают разные — консольные, с графическим интерфейсом, специфические сайты или в виде библиотек для различных языков программирования… всего чуть больше 30 софтин.

Хотя система и централизованная, «сервер» не обязательно должен быть одной машиной — можно намутить всяких репликаций, проксей, брокеров и дополнительных серверов для более равномерного распределения нагрузки и/или уменьшения времени простоя. Для клиента это всё будет прозрачно, как будто он работает с одним физическим сервером.

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

  • в геймдеве работают не только программисты и им тоже нужно уметь пользоваться системой контроля версий. Тут множество художников, звуковиков, геймдизайнеров и много кого ещё, кто с одной стороны постоянно пользуется системой контроля версий в своей работе, а с другой — не хочет разбираться во всех этих хитросплетениях графов веток, точек слияния и пересылки изменений в распределённой среде. Для них перфорс предлагает простою идею:
    1. обнови файл прежде чем с ним работать
    2. пометь что ты сейчас работаешь с ним
    3. после работы отдай свои изменения в хранилище, хотя можно даже просто смотреть что поменялось на диске и помечать файлы как изменённые уже постфактум.

    Эту идею легко объяснить кому угодно, всё настроить-обучить и в ней человеку сложно сделать что-то не так. Так же это всё легко автоматизируется и встраивается во всякие там редакторы и прочий инструментарий.

    Подобная простота основного сценария использования есть и в Subversion, но так как там все изменения обычно ищутся уже постфактум, легче нарваться на конфликты. Стандартная модель использования гита — с кучей веток, слияниями, rebase и распределённостью слишком сложна для неподготовленного человека. Да и для подготовленного она становится понятна только после изучения внутреннего устройства гита, потому что многие вещи существуют там просто «потому что эта штука была именно так сделана».

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

Чем же так эффективен перфорс при работе с бинарными файлами? Тут тоже два основных момента: во-первых, можно не скачивать то что не нужно, а во-вторых, тут есть система типов файлов.

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

Perforce для этого применяет так называемые маппинги. По-сути это набор масок, определяющих что и куда отображается в конкретном случае (отображение хранилища на компьютер пользователя или, например, отображение одной ветки на другую при интеграции и т. п.). Это позволяет легко оперировать лишь «нужными» файлами и не трогать «ненужные» (программисты могут не скачивать себе и вообще не видеть исходники всяких там текстур, художники же наоборот могут скрыть от себя исходный код и т. п.). Собранная по этим маскам группа файлов воспринимается всё равно как единое целое, её можно в одно действие обновить/откатить/залить все изменения и т. п. Так-как perforce — централизованная система, история вообще не будет скачена на локальную машину, не будет занимать на ней место и обновления будут быстрее из-за пересылки только одной версии файла вместо всех пропущенных.

Система типов в perforce гибче обычного «текст» и «не текст». На основании специальных масок (карта типов, typemap — отображение маски на тип), файлам или даже целым деревьям файлов присваиваются те или иные типы. Например, текст может быть простым ansi, а может и юникодом. Ссылки можно хранить как ссылки, а бинарники они и в Африке бинарники (есть ещё пара-тройка не столь важных типов).

Теперь начинается самое интересное — ко всему этому есть модификаторы. Модификатор определяет как файлы этого типа будут храниться и что с ними будет происходить при тех или иных операциях. Например, можно поставить модификатор для атрибутов файла и тогда на клиенте файлы этого типа будут сразу помечаться соответствующими атрибутами (доступный для записи, исполняемые). Есть модификатор для подстановки классических меток RCS, что бы в текстовых файлах прошивать какой они версии и т.п. Можно установить «эксклюзивность» файлов и тогда они будут лочиться на время любой операции (как будто клиент явно поставил бы блокировку в начале операции). Хотя текстовые файлы по-умолчанию и хранятся как набор изменений к базовой версии, можно попросить явно хранить каждую ревизию полным файлом как у бинарных файлов (можно ещё попросить сжимать эти файлы). А ещё можно попросить хранить не все ревизии — например только N последних.

Последняя опция позволяет хранить лишь несколько последних ревизий во всяких генерённых данных. С одной стороны их можно откатывать и как и всё остальное, но при этом и хранилище не так безумно разрастается. Кстати, не нужные части хранилища (например старые проекты) можно вообще архивировать и выгружать в какой-нить тёмный уголок, чтоб и сервер работал лишь с более-менее востребованными и современными данными (а если понадобятся старые — разархивировать и загрузить обратно в сервер, он всё время будет знать о них, просто не будет давать доступ к содержимому выгруженных в данный момент файлов).

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

Вот примерно по-этому я и считаю перфорс универсальной системой контроля версий для разработки игр:

  • он прост и понятен людям
  • он позволяет эффективно обрабатывать не только текстовые файлы
  • не смотря на централизованность, он достаточно масштабируем
  • для продвинутых пользователей у него есть полезные фишки в рукове
Advertisements

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

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s