SerializeReference Tooling
Ссылки на переименованные и удалённые классы находятся по всему проекту и чинятся разом — раньше, чем в сборке они станут null.
Быстрый старт
Двоичные ассеты и нескачанные файлы Git LFS молча пропускаются: оставьте Asset Serialization → Mode в Force Text (стоит по умолчанию) и скачайте файлы LFS до проверки.
Project References: восстановить группу
Project References и Asset References — вкладки одного окна. Scan Project читает файлы .prefab, .asset и .unity под Assets/, кроме Excluded scan folders.


Действия с группой
| Группа | Кнопка в заголовке | Строка под заголовком |
|---|---|---|
| Потерянный тип | Fix all ▼ — выбрать класс для всех записей | Smart Fix → Pistol — применить класс с тем же или похожим именем; причина в подсказке |
Переименование с [MovedFrom] | Reassign all ▼ — выбрать другой класс вместо нового имени | Migrate all → Crossbow — записать новое имя, см. Миграции |
Каждое действие спрашивает подтверждение Rewrite. <None> в выборе класса очищает ссылки группы и удаляет их данные, включая поля с тем же rid; он спрашивает Clear и Undo не имеет.
Что сохраняется при восстановлении
Восстановление переписывает только класс, пространство имён и сборку записи; её данные и rid остаются. Если поля группы разных типов, выбранный класс может подойти не всем: несовместимые записи станут null при переимпорте.
В сводке перезаписи есть Undo: он возвращает прежний класс записям, в которых всё ещё стоит новый. Undo пропадает после Rescan, закрытия окна и перезагрузки домена; Edit → Undo перезапись не отменяет.
Экземпляры префабов
Потерянный класс, заданный через override экземпляра префаба, — в варианте, вложенном префабе или экземпляре в сцене, — показывается в отдельной карточке Prefab instance overrides.


Fix all, Smart Fix, Migrate all и <None> такие записи не переписывают: выберите новый класс на экземпляре в инспекторе или отмените override. В Asset References ссылки, которые есть только в override, не видны.
Asset References: разобрать один ассет
Укажите сохранённый префаб, ScriptableObject или сцену в поле рядом с Rescan либо щёлкните строку записи в Project References.


| Обозначение | Значение |
|---|---|
| Полоса с Fix Missing ▼ | Сохранённый класс не найден; кнопка открывает выбор класса |
| Строка Smart Fix → Pistol | Класс, подобранный как у Smart Fix в Project References |
| Строка Migrate → Crossbow под полосой Fix ▼ | Класс переименован с [MovedFrom]: строка записывает новое имя, Fix ▼ выбирает другой класс |
| Полоса с Change ▼, Assign ▼ или Assign Required ▼ | Меняет класс исправной ссылки, заполняет пустое или обязательное поле; ассет сохраняется сразу |
| SHARED | Несколько полей указывают на один экземпляр; одинаковый цвет отмечает связанные поля |
| Orphaned | Запись, на которую не указывает ни одно поле; Clear удаляет её из файла, без Undo |
Fix Missing, Smart Fix и Migrate записывают класс в файл сразу, без подтверждения, и Edit → Undo его не отменяет.


Миграции с MovedFrom
Если CrossbowLauncher переименован в Crossbow с [MovedFrom], Unity загружает старые ссылки сам. Migrate all записывает новое имя в файлы, чтобы атрибут можно было удалить:
| В файле — до Migrate all | После |
|---|---|
type: {class: CrossbowLauncher, …} | type: {class: Crossbow, …} |
Группа становится ожидающей миграцией, только если старое имя указано в [MovedFrom] ровно у одного подходящего полю класса, а сохранённый класс — не закрытый generic; проверки сборки такую группу потерянной не считают.
Удаляйте [MovedFrom], только когда старое имя не осталось ни в одном файле. Migrate all не переписывает его:
- в override экземпляров префабов;
- в открытых, несохранённых и заблокированных файлах, см. ограничения;
- в папках из Excluded scan folders;
- в двоичных ассетах и нескачанных файлах Git LFS;
- в файлах вне
Assets/.
Проверка перед сборкой
Строгость проверки задаёт настройка Build / CI gate:
| Режим | Сборка плеера | Отдельный CI-запуск |
|---|---|---|
Off | Проверка пропускается | Ни поиска, ни отчёта, старый отчёт остаётся; код 0 |
Warn | Предупреждение, сборка продолжается | Отчёт и нарушения в журнале; код 0 |
Fail | Потерянные типы прерывают сборку | Отчёт; код 1 при нарушениях |
Сборка проверяет все ассеты под Assets/, а не только попадающие в неё: в режиме Fail её остановит и неиспользуемый префаб — исключите такие папки в Excluded scan folders.
Что проверяет каждый запуск
| Запуск | Потерянные типы | Пустые поля с Required = true |
|---|---|---|
| Project References → Scan Project | Да, вместе с ожидающими миграциями | Если режим не Off, отдельной группой Required violations |
| Asset References | Да | Да, в любом режиме |
| Сборка плеера | Если режим не Off | Нет |
CI без -srGateRequired | Если режим не Off | Нет |
CI с -srGateRequired | Если режим не Off | Если режим не Off |


Обязательное поле задаёт [TypeSelector(Required = true)], подробнее — в разделе Обязательное поле. В сценах у проверки Required есть ограничения.
Запуск в CI
Unity -batchmode -projectPath . \
-executeMethod \
Aspid.FastTools.SerializeReferences.Editors.SerializeReferenceCiGate.RunCheck \
-srGateReport SerializeReferenceGateReport.txt \
-srGateRequired -srGateFail
Код выхода 2 означает сбой самой проверки.
Флаги запуска
| Флаг | Действие |
|---|---|
-srGateReport <path> | Путь отчёта от корня проекта, по умолчанию SerializeReferenceGateReport.txt; папка должна существовать, файл перезаписывается |
-srGateRequired | Дополнительно проверить незаполненные поля с Required = true |
-srGateFail | Использовать Fail вместо режима проекта, даже Off |
-srGateWarnOnly | Использовать Warn вместо режима проекта, даже Off; важнее -srGateFail, если переданы оба |
Отчёт
Отчёт начинается с заголовка:
# SerializeReference Gate Report
# Violations: 2
# Not scanned (not text YAML): 2
# Binary Assets/Legacy/OldLoadout.prefab
# LfsPointer Assets/Levels/Arena.unity
Пропущенные файлы не меняют код выхода.
Дальше — по строке на нарушение, поля разделены табуляцией:
KIND assetPath fileId rid className fieldPath origin
| Поле | Содержимое |
|---|---|
KIND | MissingType или RequiredUnset |
assetPath | Путь файла |
fileId | Идентификатор объекта-владельца внутри файла; для override экземпляра префаба — идентификатор экземпляра |
rid | Идентификатор managed-ссылки; в строках RequiredUnset — -2 для пустого [SerializeReference] и 0 для string и SerializableType |
className | Сохранённое имя класса для MissingType |
fieldPath | Путь обязательного поля; для MissingType из override — переопределённое поле; иначе пусто |
origin | override для типа, заданного override экземпляра префаба; иначе пусто |
В Asset References запись находится по rid, строка RequiredUnset с rid 0 — по fieldPath; строка с origin override — в карточке Prefab instance overrides в Project References.
Настройки
Все настройки собраны в Tools → Aspid 🐍 → FastTools → Settings; общие есть и в Project Settings → Aspid.FastTools → SerializeReference, личные — в Preferences → Aspid.FastTools → SerializeReference.


| Настройка | По умолчанию | Что делает |
|---|---|---|
| Build / CI gate | Warn | Задаёт строгость проверки перед сборкой и в CI |
| Excluded scan folders | Нет папок | Папки внутри Assets/, которых не касаются Project References, проверки сборки и CI и Breakage detection |
| Auto de-alias duplicated list elements | Включена | Даёт продублированному элементу списка собственный экземпляр вместо общего rid |
| Breakage detection | Включена | После изменения скриптов или ассетов сообщает о новых потерянных ссылках уведомлением и в Console |
Breakage detection хранится локально в EditorPrefs, остальные настройки — в ProjectSettings/SerializeReferenceSharedSettings.asset, общем для команды и CI.
Ограничения
| Где | Ограничение |
|---|---|
| Открытые сцены, Prefab Mode, несохранённые и заблокированные файлы | Перезапись их пропускает: сохраните и закройте файл или исправьте поле через Fix в инспекторе |
| Сцены и поля под потерянной родительской ссылкой | Asset References меняет только потерянные типы |
| Required в сценах | Не проверяются поля внутри managed-ссылок, в коллекциях и в override префабов |
Пример в пакете
Потерянные типы, переименование через [MovedFrom] и общая ссылка для обеих вкладок есть в ассетах примера SerializeReferences.