Как стать автором
Обновить
725.11
OTUS
Цифровые навыки от ведущих экспертов

Ассет-менеджер для Unity на стероидах

Уровень сложностиСредний
Время на прочтение19 мин
Количество просмотров1.7K
Автор оригинала: Robert Wetzold

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

«Отобразить все модели автомобилей, которыми я владею»

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

Форматы

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

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

  • Файлы с расширением .unitypackage — это, по сути, tar‑архивы, содержащие четко определенную, но довольно неочевидную структуру папок.

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

Пакеты из реестра
Пакеты из реестра

Источники пакетов

Пакеты ассетов Unity чаще всего загружаются из Unity Asset Store (бесплатно или после покупки), но есть и сторонние магазины, например Synty. Также пользователи могут экспортировать свои собственные пакеты, например, чтобы сделать их повторное использования в других проектах более удобным.

Пакеты второго типа чаще всего можно найти в центральном реестре Unity, но у пользователей также есть возможность настроить свой собственный удаленный реестр, который будет добавлен в качестве scoped registry. Также без каких либо трудностей можно ссылаться на публичные package.json, например, Github или даже локальные репозитории.

Пример, демонстрирующий работу Unity, scoped registry, веб‑ и локальных ссылок в проекте
Пример, демонстрирующий работу Unity, scoped registry, веб‑ и локальных ссылок в проекте

Кроме того, Unity‑разработчики зачастую накапливают на своих жестких дисках целые медиатеки с текстурами и звуковыми файлами из интернета и других источников, которые можно напрямую перетаскивать в редактор. Иногда они еще и запакованы в zip‑архивы, чтобы сохранить место на диске.

Часть моих папок с произвольными ассетами
Часть моих папок с произвольными ассетами

Дилемма

В результате вы получаете список пакетов. Метаданные для обоих типов отличаются, но обычно они содержат название, описание, примечания к выпуску, информацию об издателе и теги. Asset Store также поддерживает мультимедиа, например скриншоты и ссылки на видео, которые могут предоставить авторы, а пакеты из реестра дополнительно демонстрируют зависимости.

Список пакетов, отображаемый в менеджере пакетов Unity (2023.2)
Список пакетов, отображаемый в менеджере пакетов Unity (2023.2)

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

→ Не правда ли, этот процесс выглядит совершенно неправильно?

Действительно ли для нас важны все эти пакеты? Или нам все‑таки важнее ассеты, и не так уж важно, в каких пакетах эти ассеты содержатся? Вот в чем главный вопрос:

→ Почему вообще нашей отправной точкой служат пакеты?

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

Новая надежда

Поскольку я сам обсессивно складирую ассеты и к настоящему моменту владею более чем 2000 пакетов, этот устоявшийся процесс всегда меня расстраивал. И наконец, два года назад, я решил что‑то с этим сделать. Я начал с:

→ Как выглядел бы идеал моего рабочего процесса с ассетами?

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

Так что если опыт покупки остается прежним, то должен измениться опыт поиска. И вот тут возникает важная мысль:

→ Что, если бы мы могли производить поиск именно по ассетам, а не по пакетам. И что нам для этого необходимо?

Шаг 1 — Индекс

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

  • Unity уже хранит все загруженные пакеты (как ассеты, так и пакеты из реестра) в специальных кэш‑папках

Корневой каталог кэш‑папок Unity
Корневой каталог кэш‑папок Unity
  • Файлы .unitypackage — это просто tar‑архивы, которые можно легко распаковать

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

До четырех файлов на папку/ассет
До четырех файлов на папку/ассет

Я решил использовать SQLite, являющимся отличным форматом легковесных встраиваемых баз данных, способных легко обрабатывать миллионы записей. Я создал две таблицы: Assets и AssetFiles. В Assets содержится информация о пакете, а в второй — список связанных файлов ассетов. Затем с помощью скрипта редактора Unity я перебираю все пакеты в кэше, извлекаю их и сохраняю информацию в базе данных.

Схема базы данных SQLite
Схема базы данных SQLite

Добавим сюда новый пользовательский интерфейс, предназначенный специально для поиска, и — о чудо: вводим «car» и вуаля! (Небольшое примечание: скриншоты, показанные здесь, не являются исторически достоверными, а взяты из текущей версии)

Просмотр ассетов из шести различных пакетов
Просмотр ассетов из шести различных пакетов

С учетом ряда первых специфических случаев (которых было ОЧЕНЬ МНОГО), добиться приведенного выше результата мне удалось всего за неделю работы, и я был этим очень доволен. Поэтому я отполировал это как мог, добавил первую версию документации и создал свой первый в жизни пакет в Asset Store. Я собираюсь описать этот опыт в отдельной статье — мне кажется, что он может быть очень полезен для начинающих издателей Asset Store. В общем, через месяц этот проект был запущен в продажу, и разработчики приняли его на ура:

«Это должно быть уже интегрировано в редактор», «Трансформационная эффективность», «Феноменально!», «Колдовство», «Лучший менеджер ассетов!».

Казалось, что я попал как раз в цель и сделал что‑то действительно полезное, чего раньше не существовало. Помимо эмоционального подъема, также стало расти количество пользователей и появились кучи запросов расширения функционала. Именно этим я и занимался последние два года. Одиннадцать крупных обновлений с момента первоначального релиза и вот наконец готова версия 2.0, которая выводит все на совершенно новый уровень. Я горжусь своим сообществом, и мне нравился каждый шаг на этом пути. Но давайте будем последовательны:

Шаг 2 — Больше источников

Чтобы мы могли что‑то проиндексировать, оно должно быть доступно в локальном кэше Unity. Если у вас особенно много ассетов или вы покупаете новые, в индексе будут пробелы, пока вы их не загрузите. Пакеты в Asset Store зашифрованы, поэтому скачивать их вручную — не выход. К счастью, существует способ инициировать загрузку через Unity, в результате чего они будут скачаны и расшифрованы. Я добавил способ сделать это и сразу удалить загруженный файл, чтобы сэкономить место, так что каждый ассет будет правильно проиндексирован. Это гарантирует, что 100% ассетов из Asset Store будут проиндексированы.

Работа со свободно распространяемыми ассетами требовала иного подхода. Я создал три разных специализированных индексатора:

  • Пользовательские пакеты: Сканирует любые файлы.unitypackage и индексирует их содержимое. Первоначальным недостатком был недостаток важных метаданных из Asset Store (которые я загружаю через API), таких как информация об издателе, медиафайлы и т. д. К счастью, для этого есть два решения. Во‑первых, многие пакеты содержат заголовок, в котором указывается их ID и некоторые базовые метаданные. Используя этот ID и API Asset Store, можно загрузить дополнительные метаданные. Остается вопрос, что делать с пакетами, у которых нет заголовка, но они также доступны в Asset Store, просто куплены в другом месте? Я решил, что проще всего будет вручную вводить их Id (содержащийся в URL Asset Store, например https://assetstore.unity.com/packages/tools/utilities/asset‑inventory-226 927), чтобы таким образом подвязать их.

Пример заголовка пакета
Пример заголовка пакета
Пользовательский интерфейс для ручного указания ID
Пользовательский интерфейс для ручного указания ID
  • Медиафайлы: Сканирует изображения, звуковые файлы и 3D‑модели

  • Архивы: Сканирует.zip‑файлы и индексирует их содержимое, используя индексатор медиафайлов

Настройка дополнительных папок для сканирования и их импортеров
Настройка дополнительных папок для сканирования и их импортеров

Это покрывает и прекрасно справляется со всеми файлами, не управляемыми Unity, так что на данный момент у нас есть менеджер ассетов, который может на 100% проиндексировать все приобретенные и локально хранящиеся файлы.

Неожиданная проблема возникла в Unity 2022+, где появилась возможность настраивать местоположение кэша, не раскрывая его через API (по сей день). К счастью, у них есть несколько частных функций для сбора этой информации, и сила рефлексии да прибыла со мной.

Шаг 3 — Улучшение индекса

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

Расширенные фильтры и поиск по цвету в действии
Расширенные фильтры и поиск по цвету в действии

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

Аудиоассеты
Аудиоассеты

Следующим пунктом был поиск. При вводе слова «car» будут также выданы элементы, удовлетворяющие запросу «cards». Теперь есть два режима, позволяющие сделать поиск еще лучше:

  • «+car ‑cards»: используйте плюсы и минусы, чтобы указать, что должно встречаться в выборке, а что нет, или ~ для принудительного буквального поиска, в противном случае слова могут появляться в любом порядке.

  • «=» в начале инициирует экспертный поиск, который позволяет напрямую использовать синтаксис SQL, например «=AssetFile.Width > 3000 and AssetFile.FileName not like „%Normal%“ and Asset.DisplayName like „%icon%“».

Шаг 4 — Улучшение импорта

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

Если смотреть на проблему в лоб, то она выглядит так: такие файлы, как изображения и звуки, могут быть импортированы сами по себе. Но другие файлы в Unity будут иметь зависимости, например, префабы будут указывать на модели, материалы, анимации и так далее. А материалы будут указывать на текстуры...

Сначала я рассматривал сложную методику определения таких зависимостей, но потом понял, что есть элегантный короткий путь: каждый ассет в Unity имеет соответствующий.meta‑файл рядом с ним, обычно скрытый. Этот файл содержит различную информацию, включая GUID для уникальной идентификации. Это первая часть головоломки.

Типичный метафайл
Типичный метафайл

Другое дело, что материалы, префабы и т. д. — это просто текстовые файлы в формате yaml (если они сериализованы как текст, что происходит по умолчанию). И если у файла есть зависимости, то GUID этих файлов будут отображаться внутри этого файла.

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

Анализ зависимостей в действии
Анализ зависимостей в действии

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

И вот после долгой борьбы с этой проблемой мне в голову пришел очень простой эксперимент: что, если мы просто будем автоматически вызывать конвертер конвейера рендеринга, если мы в URP‑проекте? И даже если это немного чересчур, потому что он будет сканировать все материалы проекта (API для предоставления только одного материала нет), это удивительно эффективно и вполне справляется со своей задачей.

И так, что мы имеем: теперь мы элегантно находим отдельные файлы, выборочно импортируем их в проект и делаем совместимыми с проектом для немедленного использования. Шикарно!

Шаг 5 — Улучшение менеджера пакетов

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

Вернемся к чертежной доске: какие функции я лично хотел бы видеть в пакетах (и подсказка: следовательно, также реализованными)?

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

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

Массовая информация и действия при выборе нескольких пакетов
Массовая информация и действия при выборе нескольких пакетов
  • Теги: Я хочу иметь возможность задать теги и применить их к моим пакетам для более удобной группировки. И я хочу массово импортировать все элементы по тегу, например группу «essentials», за один раз.

  • Информация: Я бы хотел видеть всю доступную информацию о пакете, например рейтинг, последнее обновление, описание, медиафайлы, возможно, даже дату покупки и цену.

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

  • Импортирование: Я хотел бы сохранить корневую папку Assets чистой и поместить все пакеты ассетов в специальную вложенную папку. При импорте пакетов из scoped registry я хочу, чтобы этот реестр автоматически добавлялся.

  • Интеллектуальные обновления: Пакеты из реестра получают множество обновлений. Мне бы хотелось иметь один значок, указывающий на то, что появилось что‑то новое, требующее моего внимания. Но меня, например, не интересуют предварительные версии. Или интересуют, но только для конкретного пакета. Мне бы хотелось иметь возможность указать стратегию обновления для каждого пакета, и тогда я смогу понять по индикатору обновлений, что мне действительно есть что проверить и обновить, не тратя время.

Доступные стратегии обновления
Доступные стратегии обновления

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

Пример итога текущей стоимости активов
Пример итога текущей стоимости активов

Шаг 6 — Улучшение предварительного просмотра изображений

Когда я ранее показывал структуру пакета, мы видели, что в нем также хранится изображение для предварительного просмотра. Unity очень удобно генерирует их для ассетов автоматически. Техническое ограничение, которое накладывает Unity, заключается в том, что они ограничены 128×128 пикселями. Это нормально при просмотре в небольшом окне проекта, но не позволяет увеличить изображение. Размер около 256×256 был бы куда удобнее. Это одно из часто запрашиваемых сообществом улучшений.

Какие есть альтернативы? Банальное масштабирование делает изображение некрасивым. Для файлов изображений с разрешением выше 128 мы можем сами создавать превью в заданном размере и заменять ими оригиналы, получая красивые и четкие изображения. Недостатком является то, что они занимают больше места на диске. Для моего 1 миллиона проиндексированных файлов этот объем составляет уже 12 Гб (вместо примерно 6 Гб).

Параметры создания превью
Параметры создания превью

Другие ассеты, такие как префабы, сложнее. С ними, как правило, нельзя работать вне редактора Unity. К счастью, существует API PreviewSceneStage для создания превью, и, используя этот способ, мы можем сохранить эти изображения в текстуру более высокого разрешения. Этот способ используется в нескольких других ассетах для различных целей, и я планирую перенять его в будущем.

Шаг 7 — Резервное копирование

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

Однако это не относится к гораздо большей категории пакетов Asset Store, которые поставляются в виде файлов .unitypackage и, по сути, копируются 1:1 в проект. В Asset Store нет концепции возврата к более ранним версиям. Есть только последние (с небольшим отличием в виде поддерживаемой версии Unity, которая выступает в качестве верхней границы) и все, что у вас есть в локальном кэше. Как только вы загружаете новую версию, старая теряется.

У пакетов также есть жизненный цикл. Существует 3 состояния (если не считать черновики / draft, к которым имеет доступ только автор). Чтобы немного проиллюстрировать типичное распределение, вот состояния и то, сколько моих ассетов попадает в каждую категорию:

  • опубликованные / published: 1598

  • устаревшие / deprecated: 313

  • деактивированные / disabled: 29

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

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

Настройки резервного копирования
Настройки резервного копирования
Пример содержимого папки с резервными копиями
Пример содержимого папки с резервными копиями

На скриншоте папки выше видно, что версии 11.3.0 для Asset Store Publishing Tools нет, поскольку существует патч более высокой версии и старый был удален. Имея такую структуру легко вернуться к определенным версиям. Поскольку папка с резервными копиями используется нечасто, ее можно выгрузить на дешевый, большой и медленный внешний жесткий диск.

Шаг 8 — Обратный поиск

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

Здесь можно использовать несколько подходов. Быстрое решение — снова использовать GUID. Поскольку все индексируется, мы можем выполнить поиск по GUID в базе данных и узнать, к какому пакету он относится. Здесь есть две проблемы:

  • Он может принадлежать нескольким пакетам, если это общий или совместно используемый файл, загруженный из сети, или что‑то, что издатель повторно использует из пакета в пакет.

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

Пример результата обратного поиска
Пример результата обратного поиска

Чтобы решить эту проблему, нам нужно каким‑то образом запомнить, из какого пакета был установлен исходный файл. Например, мы могли бы хранить такую информацию в базе данных или в файле рядом с ассетом. Но это очень быстро выльется в полный беспорядок. Интересно, что в Unity тоже поняли, что это плохо, и в версии 2023+ добавили дополнительные атрибуты в сами метафайлы, чтобы точно определить происхождение ассета:

Новые поля AssetOrigin в метафайлах
Новые поля AssetOrigin в метафайлах

В ближайшем обновлении я включу эти поля, если они существуют.

Шаг 9 — Экспорт

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

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

Экспортер ассетов для выбранных групп типов файлов
Экспортер ассетов для выбранных групп типов файлов
  • Экспорт метаданных: информация о пакете должна быть доступна в формате CSV для быстрого импорта в Excel и другие электронные таблицы для анализа.

Экспортер CSV с настраиваемыми полями
Экспортер CSV с настраиваемыми полями
  • Доступ к первичным данным: это наиболее универсальный доступ, который можно использовать для создания пользовательских веб‑фронтэндов и тому подобного (это действительно было сделано в одном университете). SQLite — широко используемая база данных, и взаимодействие с ней очень простое, почти не доставляет неудобств.

Шаг 10 — Один индекс на несколько устройств

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

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

Захардкоженные пути в базе данных
Захардкоженные пути в базе данных

После долгих поисков лучшим решением показалось введение концепции ключей, которые кодируют физическое расположение диска. Так, вместо «c:/temp» будет просто «[temp]». Затем на каждом компьютере этот ключ нужно будет один раз сопоставить с конкретным путем на конкретном устройстве. Я написал инструмент для удобного преобразования захардкоженных путей в ключи и обратно, а также для отслеживания количества компьютеров, обращающихся к базе данных.

Мастер преобразования для использования на разных устройствах, [Изображения] уже являются относительными
Мастер преобразования для использования на разных устройствах, [Изображения] уже являются относительными

Шаг 11 — Третьи лица и API

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

Лучший способ сделать это — положиться на автоматический символ define для C#. Таким образом, вы можете написать код, который будет компилироваться только в том случае, если ассет доступен, в противном случае ошибок компиляции не будет.

Пример API‑вызовов к инвентарному списку ассетов
Пример API‑вызовов к инвентарному списку ассетов

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

Пример вызова API с использованием эвристики текстур
Пример вызова API с использованием эвристики текстур

Заключение и перспективы

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

Последние два года я использую Asset Inventory почти каждый день, как во время разработки, так и при работе над малыми и большими проектами. Это первое, что я обычно устанавливаю, и он экономит мне очень много времени.

Во второй версии я наконец‑то достиг того состояния, когда могу с уверенностью назвать его менеджером пакетов 2.0, который превосходит встроенные функции Unity почти на каждом уровне и во многих отношениях намного глубже, а также обратно совместим вплоть до Unity 2019.4.

Это один из моих самых амбициозных проектов, над которым я когда‑либо работал. Он закончен? Безусловно, он прошел очень долгий путь. Он прошел боевые испытания большим сообществом и готов к продакшену. Роадмап в Trello наконец‑то стал меньше, но все еще длинный, и мне не терпится решить следующие задачи.


Статья подготовлена в рамках онлайн-курса "Unity Game Developer. Professional". Если хотите систематизировать знания по архитектуре и разобраться с принципами и паттернами проектирования — пройдите вступительное тестирование для оценки уровня знаний и получите скидку на обучение.

Теги:
Хабы:
+5
Комментарии0

Публикации

Информация

Сайт
otus.ru
Дата регистрации
Дата основания
Численность
101–200 человек
Местоположение
Россия
Представитель
OTUS