Валидация
Как SDK проверяет уровень по правилам формата, чинит то, что можно починить, и сообщает о том, что нельзя
Валидацию вы вызываете сами. В сохранение и загрузку она не встроена
Где её запускать, решает игра. Открытие уровня в редакторе сообщает о проблемах, а воспроизведение проверку пропускает. Поэтому валидации ждёт автор, а игрок - никогда
Автор уровней встречается с валидацией, когда предлагает уровень сервису. Подробнее - Профили публикации
Как вызвать
ValidationFacade - единая точка входа. Вызывающему не нужно знать, сколько проходов существует:
var facade = new ValidationFacade();
var report = facade.Validate(level);
if (report.HasErrors)
Console.WriteLine(report);
| Метод | Что делает |
|---|---|
Validate(root, settings) | проверяет любой корень: Level, LevelMeta, UserSettings, отдельный Prefab или EffectData. Проход по графу запускается только для Level |
ValidateAndFix(root, analyzerSettings, fixerSettings) | чинит то, что можно, и сообщает об оставшемся |
ValidateForPublish(meta, profile, level, now, payload, settings) | все три прохода сразу, ничего не чинит. level может быть null, чтобы оценить только метаданные |
ValidationReport содержит RuleIssues и GraphIssues:
IsValid- находок нет совсемHasErrors- есть хотя бы одна находка группыError
Серьёзность
Каждое правило относится к RuleGroup:
Error- файл нельзя сыграть в том виде, как он записанWarning- играется, но не так, как задумано (содержимое, которое никогда не появится, битая ссылка с запасным вариантом). Или единственная починка разрушительнаAdvice- воспроизведение не меняется
Три прохода
| Проход | Что спрашивает | На чём работает |
|---|---|---|
RuleAnalyzer | каждое ли значение в своём диапазоне, не null, известный член перечисления | любой корень |
LevelGraphAnalyzer | согласуются ли объекты друг с другом | только Level |
PublishReadinessAnalyzer | можно ли отдать уровень чужим людям по данному профилю | LevelMeta, по желанию Level |
Правила
Тип включается в проверку маркером [RuleContainer]. Его свойства несут атрибуты правил:
[RuleNotNull],[RuleInRange],[RuleMinValue],[RuleEnumValid],[RuleCollectionMaxCount]и другие[RuleEnumFlagsValid]- для флаговых перечислений[RuleOptional]- для поля, которое может отсутствовать
Сами пределы - константы в таблицах Rules/: FrameRules, ValueRules, LevelRules и другие. Например, LevelRules.MaxObjects равен 262 144
Обход всех контейнеров правил генерирует BH.SDK.Roslyn, без рефлексии. На больших уровнях это примерно вдвое сокращает его время
Исправления
Каждый атрибут правила умеет чинить своё значение (Fix).
RuleFixer применяет починки в обратном порядке трассы: починка может сдвинуть более глубокие находки. ValidateAndFix повторяет проход, пока результат не перестанет меняться
Проход по графу идёт после починок. Починка сама может создать проблему в графе, например новый id, совпавший с существующим
Находки графа не чинятся никогда: DuplicateObjectId, MissingParent, ParentCycle, PrefabRemapBroken, IdCounterNearExhaustion и остальные. Каждая такая починка - решение о содержимом (какой из двух объектов сохранит свой id). Догадка переписала бы уровень
ValidateAndFix меняет объект, который вы передали. Запускайте его на копии, если вам нужен оригинал, например чтобы показать автору, что именно изменилось