Совсем недавно я понял, что с ростом количества готовых проектов мне приходится уделять все больше времени сборке билдов.
Нельзя сказать, что Unity как-то сильно усложняет этот процесс, но и не упрощает его.
Особенно когда каждый проект собирается под несколько платформ и в разных конфигурациях.
В принципе, проблема не нова и имеет множество различных решений.
Но по ряду причин я решил написать собственный плагин.
Это выглядит примерно так:
Ниже я расскажу почему, где его взять и как его использовать.
Боль
Первый дискомфорт обычно ощущается, когда к выпуску готовится более одной платформы.Получается, что в Unity некоторые настройки проекта являются общими для всех платформ, а некоторые — нет. И это всегда нужно помнить и учитывать.
Но в целом жить можно.
Тогда оказывается, что сохранять разные настройки в пределах одной платформы невозможно.
Простой пример: есть одна сборка, но есть множество платформ, на которых она будет распространяться.
И каждому нужно что-то свое.
Эта проблема частично решается путем переноса настроек в конфигурацию времени выполнения в StreamingAssets. Но лишь частично, потому что таким образом вы сможете настроить лишь то, что уже происходит внутри игры.
Вы не можете изменить значок таким образом.
Иконку каждый раз приходится менять самостоятельно.
Будь то кодом или вручную, но самостоятельно.
И в какой-то момент ответственный менеджер, которого вы месяц обучали работе со StreamingAssets, уходит в отпуск, а билды нужны еще вчера.
Еще позже вы узнаете, что планируется отдельная корейская версия, там все должно быть иначе и без #ifdef не обойтись.
А потом вам говорят, что игру нужно запустить на мобильных платформах PlayStation, Nintendo и стиральных машинах.
В результате подготовка каждого нового билда со временем становится примерно такой:
Проверьте показания прибора, включите тумблер слева, поверните рычаг справа, затяните красный вентиль.
Ничего не перепутайте и не забудьте.
Поначалу это может быть и нормально, но быстро надоедает. И вспомните все манипуляции через месяц-два.
Какие у вас есть варианты?
Интернет и народная мудрость предлагают нам следующее:- Решите проблему на уровне проекта.
Реализации этого подхода могут быть разными: отдельные проекты с общим кодом и активами, подмодули в git, ветки в git и тому подобное.
Я не могу серьезно об этом думать.
Оградить сад ради замены иконы, а потом еще и поддержать ее.
Совсем на любителя.
Но я видел это своими глазами, поэтому не мог не упомянуть об этом.
- Скрипты Bash/bat/python/….
Уже теплее.
Но это требует дополнительных знаний и вряд ли можно назвать кроссплатформенным (часто часть команды разрабатывает под Mac, часть под Windows).
Опять же, скрипты нужно поддерживать, а на это не всегда есть время.
- Редактор скрипта в самом модуле.
Довольно тепло.
Переворачиваем проект внутри Unity так, как хотим.
А если использовать статический метод и BuildPipeline, то можно настроить CI. Как правило, это то, что описано в статьях про Unity и CI. Однако здесь остается один недостаток предыдущего подхода: это код и его надо писать, модифицировать и поддерживать.
Нам нужно что-то подобное, но без необходимости вникать в код каждой платформы и конфигурации.
Мы пишем собственный плагин с пользовательским интерфейсом и феями.
Нам нужен план
Для начала нам нужно решить, что мы на самом деле хотим получить и почему.
- Хранение настроек проекта для каждой конфигурации (здесь можно переключиться на терминологию самого плагина и назвать их опциями).
Целесообразно реализовать вариантное наследование.
Например, для всех автономных сборок настройки проекта будут общими, а опции будут отличаться друг от друга только иконкой и названием проекта.
Вполне логично решить это наследованием, а не копипастом.
- Наглядное представление того, что было изменено в той или иной опции и чем она отличается от текущих настроек проекта.
- Объединение вариантов в коллекции.
Чтобы иметь возможность собирать сразу определенное подмножество билдов одной кнопкой или одним статическим методом.
- Упаковка сборки в архив.
Это необязательное требование.
Если плагин используется совместно со сборочным сервером, этот пункт можно реализовать на его стороне.
Но хочется всем облегчить жизнь, а билд-сервер не всегда доступен.
- Перемещение файлов на разных этапах сборки.
Например, вам необходимо заменить какой-то ассет (иконка, заставка, сцена и т.д.) перед сборкой (замена ассетов должна быть обратимой, сборка сборки не должна менять текущее состояние проекта).
Либо переименуйте {exe_name}_Data в Data в готовой сборке Windows (очень раздражающее поведение модуля, без этой манипуляции переименовать экзешник не получится).
Или опять же поместите необходимые StreamingAssets в сборки Windows. Это необходимо сделать перед упаковкой архива.
А потом, например, перетащить все архивы куда-нибудь в одно место.
- Unity-проекты имеют огромное количество настроек и нам совершенно не хочется писать для них свой собственный UI. Тем более, что он уже есть в самом агрегате.
Поэтому мы будем менять настройки проекта как обычно, а в плагине просто будем отслеживать изменения настроек и сохранять их в нужные опции.
- Я хотел бы сохранить каждый вариант в отдельном файле, чтобы можно было перетаскивать их между проектами.
- Желательно, чтобы он работал с Unity начиная с версии 5.6. Существует ряд устаревших проектов, вокруг сборок которых много шума.
Пойдем
Основная часть нашего плагина — это работа с настройками проекта, а также хранение и обработка настроек отдельных опций.Поэтому мы сосредоточим на этом свое внимание.
Все настройки Unity хранятся в каталоге ProjectSettings в корне проекта.
И первым делом при инициализации мы сохраним эти настройки в директории плагина (кстати, это BuildVariants в корне проекта).
Это потребуется для того, чтобы мы могли отслеживать все последующие изменения.
Далее нам нужно их как-то сохранить.
Проще всего было бы просто скопировать ProjectSettings в отдельное место для каждого параметра.
А в момент его активации просто замените их целиком.
Идея вполне работоспособная и поначалу я ее обдумывал.
Но это полностью лишает нас возможности наследовать варианты.
А если мы уже пишем плагин, то сразу сделаем это красиво.
Это означает, что нам нужно научиться читать и записывать содержимое ProjectSettings. Для этого нужно понять, что там хранится.
И там хранятся самые обычные активы, которые сериализуются и десериализуются обычным способом.
Это означает, что мы можем прочитать их через AssetsDatabase и получить SerializedObject. Это уже что-то.
Потому что мы можем перебирать все SerializedProperty, отслеживать их различия с исходным «снимком» и сохранять их в варианте.
Затем при сборке или активации варианта собираем изменения по всей цепочке наследования, применяем их к «снимку» и вставляем в ProjectSettings. Вуаля.
Но у SerializedProperty есть некоторые неприятные особенности: способ хранения значений (все эти intValue, floatValue, isArray), отсутствие нормального механизма их сравнения (есть два связанных объекта, как понять, если все SerializedProperty имеют одинаковые значений) и парадоксальное (а может и отсутствие) отсутствие атрибута Serializable (а это значит, что нам понадобится какая-то обертка для сохранения).
Не могу сказать, что это какие-то фатальные недостатки.
Все это делалось не раз в многочисленных скриптах редактора.
Но мне все же хочется чего-то более простого, понятного и универсального.
Или может быть немного ограничим использование нашего плагина? Пусть работает только на проектах с текстовой сериализацией ассетов (кто-нибудь еще использует бинарную сериализацию?).
Тогда все ProjectSettings будут сохранены в виде документов yaml. Вы можете взять библиотеку YamlDotNet и использовать ее для анализа и сохранения настроек.
При этом сохраняйте свои конфиги в yaml. Так еще яснее.
Вам просто нужно добавить несколько расширений для различия документов yaml и их объединения.
Немного повозился с окном редактора (даже не хочу описывать, надеюсь, что с UIElements жить станет проще и веселее), собрал все воедино и готово.
Результат
Пришло время показать что я сделал? .С основными механизмами работы плагина вы уже ознакомились, поэтому кратко расскажем о некоторых его возможностях:
- Опции добавляются в выбранную коллекцию с помощью галочки слева от названия.
- Путь сборки должен быть указан с расширением.
Полный список расширений для всех возможных BuildTargets я не нашел, поэтому оставил пока так.
- Перемещение файлов наследуется так же, как и настройки.
- Разница в массиве не реализована.
Поэтому если в унаследованной версии вы что-то изменили в списке сцен, то весь список будет заменен целиком.
Для хорошей меры его необходимо будет улучшить.
- Разница в фактических настройках проекта — это список всех различий между выбранной опцией и текущими настройками проекта.
При этом если выбрана активная опция, то изменения текущих настроек можно отменить.
- Вариантные настройки — это, соответственно, индивидуальные изменения выбранного варианта без учета родительских изменений.
- При активации этой опции все несохраненные изменения настроек проекта будут потеряны.
- Если в настройках проекта есть несохраненные изменения, то любая попытка собрать сборку через плагин закончится исключением.
Потому что см.
выше, и как мы помним, «сборка сборки не должна менять текущее состояние проекта».
- Плагин можно использовать вместе с сервером сборки.
Для этого существуют статические методы: BuildVariants.Controller.BuildController.BuildAll, BuildVariants.Controller.BuildController.BuildCollection (с именем коллекции в параметре -collection) и BuildVariants.Controller.BuildController.BuildVariant (с именем варианта в -variant) параметр).
Это будет выглядеть примерно так:
$unity_path -batchmode -projectPath $project_path -quit -logfile -executeMethod BuildVariants.Controller.BuildController.BuildCollection -collection standalone
- Для включения архивирования у плагина есть еще одна зависимость в виде библиотеки DotNetZip.
- Плагин писался в условиях небольшого рабочего затишья, поэтому у нас пока не было возможности протестировать и закалить его в жестоких боях.
Могут быть баги, возможно даже плохие и неприятные.
Планы на будущее
Конечно, хочется накормить плагин возможностями до бесконечности, но пора вернуться к реальным проектам, а заодно и протестировать существующий функционал.Чуть позже хочу использовать UIElements для последних версий Unity, надеюсь от этого все станет красивее и удобнее.
Я также хотел бы добавить управление версиями и некоторые переменные среды.
Возможно, публика сможет предложить что-то еще относительно функциональности или удобства использования.
Поэтому буду рад любым предложениям, комментариям, вопросам и сообщениям об ошибках.
Легкая сборка для вас! Теги: #Разработка игр #Игры и игровые консоли #unity #непрерывная интеграция #unity3d #расширение редактора unity3d
-
Постоянный Бар
19 Oct, 24 -
2Гис – Гостиничный Эксперт
19 Oct, 24