Все статьи
Туториалы · 7 min read

Приручить библиотеку из 100 000 ассетов, пока она не приручила вас

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

Illustration of an asset thumbnail grid with a search field and tag chips

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

Читальный зал библиотеки, стеллажи в тёплом свете Библиотека складывается не из кучи книг, а из книг плюс системы поиска. Ваша коллекция ассетов становится библиотекой лишь тогда, когда вторая часть существует; иначе это очень дорогая куча.

Настоящая цена беспорядочной библиотеки

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

Ущерб виден на экране: повтор, что игроки чувствуют, деньги, потраченные на паки, которые никогда не выходят, и тихий налог на каждый час дрессинга. Есть острее способ сформулировать правило: ассет, который нельзя найти примерно за минуту, фактически не существует. Вы заплатили за него, храните, бэкапите, а он никогда не появится в уровне. Находимость — не уборка; это верхняя граница вашего визуального разнообразия. Две студии с одинаковыми бюджетами ассетов выпустят видимо по-разному выглядящие игры, если одна может найти свои ассеты, а другая нет.

Именование: скучное, сортируемое, однозначное

Соглашение работает лишь, если полезно сортируется в плоском списке: префикс типа, категория, материал или вид, размер, индекс. Без пробелов, без «final_v2_NEW».

Проверенная форма:

SM_Rock_Granite_Large_01        (static mesh)
SM_Rock_Granite_Large_01_LOD1
T_Rock_Granite_D / _N / _R      (textures: diffuse, normal, roughness)
M_Rock_Granite                  (material)
MI_Rock_Granite_Mossy           (material instance)

Правила, что держат это в масштабе: одно слово на понятие (Rock, не Rock/Stone/Boulder вперемешку), ставьте поле, по которому чаще всего фильтруют, рано, чтобы сортировка полезно группировала, дополняйте индексы нулями (01, не 1), чтобы 10 не сортировался перед 2, и напишите соглашение на одной странице, что читают все в первый день. Точная схема важна куда меньше, чем наличие ровно одной, и начать сегодня, при любом размере, потому что задним числом надевать имена на 50 000 файлов — проект, который никто никогда не заканчивает и об отсрочке которого все жалеют.

Папки говорят одно; теги говорят остальное

Файл живёт в ОДНОЙ папке, но имеет много свойств: папки должны кодировать владение и пайплайн (какой пак, какой проект), теги кодируют всё, по чему вы бы искали: биом, материал, настроение, размер, стиль.

Борьба с многомерностью более глубокими деревьями папок рождает классическое кладбище Props/Nature/Trees/Dead/Moss/, где ничто больше не находится, потому что замшелая мёртвая берёза принадлежит пяти папкам разом и может жить лишь в одной, так что всегда в неверных четырёх. Рабочее разделение делает поиск главным путём внутрь, а дерево папок остаётся лишь трубопроводом.

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

Миниатюры решают качество поиска

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

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

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

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

Дубликаты: одно оставить, остальные пометить

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

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

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

Миграция: от хаоса к системе

Никогда не ставьте продакшн на паузу ради уборки одним махом: применяйте соглашение ко всему НОВОМУ с сегодня, затем мигрируйте старый контент оппортунистично: что уровень втягивает, переименовывается и тегируется по ходу.

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

Полевые цифры, которые стоит украсть

  • Бюджет находимости: меньше 1 минуты, иначе ассет функционально не существует
  • Словарь тегов, покрывающий работу над окружениями: ~5 осей, ~40 закрытых терминов
  • Скорость сканирования миниатюр при согласованном рендере: сотни в минуту
  • Политика дубликатов: понизить немедленно, удалить через ~6 месяцев без ссылок
  • Именование: индексы с ведущими нулями, одно слово на понятие, одна страница правил

Мини-FAQ

Достаточно ли хороши ИИ-теги, чтобы заменить ручной теггинг? Достаточно, чтобы заменить бо́льшую часть: автоматические теги несут основную массу (предмет, материал, цвет), а люди добавляют оценочные решения (подходимость стиля, проектные термины). Комбинация бьёт каждое поодиночке, поэтому ИИ-теггинг лучше всего работает как опциональный вспомогательный слой, а не полная замена.

Одна общая библиотека или по проектам? Общая исходная библиотека, поимпортные проекты. Библиотека хранит всё с полными тегами; проект втягивает лишь то, что выпускает, держа билды поджарыми, а времена cook короткими. Смешать оба (проект, референсирующий всю библиотеку): так и раздуваются размеры билдов.

А версионирование бинарных ассетов? Библиотека — сад, не архив: версионируйте исходные файлы в вашем DCC-пайплайне, держите библиотеку как только-текущее-лучшее. Исторические версии, живущие в результатах поиска, превращаются в шум с именной табличкой и замедляют каждый поиск для всех.

Как заставить команду реально следовать соглашению? Сделайте правильное лёгким: шаблон сохранения/импорта, что предзаполняет паттерн имени, шаг линта, что помечает файлы вне соглашения, и миниатюры, что делают соглашённые ассеты находимыми, а несоглашённые — невидимыми. Соглашение, внедрённое инструментами, держится; внедрённое нытьём — нет.

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