Решили: своя dev-консоль (Трек К) строится на явном реестре команд — модуль сам объявляет свои
команды через DevCommandRegistry.Register, никаких атрибутов и сканирования сборок. Экран —
ScreenKind.Modal с SuppressScrim = true, автодополнение — ghost-подсказка под полем ввода, а не
цикл по Tab; отсюда моноширинный шрифт (Fira Mono, SDF с динамическим атласом).
Почему: атрибутная модель QFSW удобна ровно до первого вопроса «откуда метод возьмёт зависимости» —
статический метод с [Command] вынужден сам добывать сервисы, и именно так в проект возвращаются ходы к
синглтонам мимо VContainer. Явная регистрация оставляет граф зависимостей видимым и заодно делает реестр
тестируемым без сцены (21 EditMode-тест). Цена — команду нужно объявить руками; на четыре десятка команд
это дешевле, чем рефлексия со стриппингом на IL2CPP.
Ghost вместо Tab-цикла: цикл заставляет угадывать, сколько раз нажать, а дорисованный остаток виден
сразу. Он требует совпадения символ-в-символ с полем ввода — значит моно; на пропорциональном шрифте
призрак уезжает вправо на первой букве. SuppressScrim — потому что консоль открывают, чтобы
РАЗГЛЯДЫВАТЬ кадр под ней: затемнять его значит работать против собственной задачи.
Грабли:
- Числа обязаны парситься в
CultureInfo.InvariantCulture. Локаль машины русская, десятичный разделитель — запятая, иgm_sep_ally 0.35без явной культуры отвергался бы как мусор. Синтаксис инструмента не зависит от языка системы; сторожитDevConsoleRegistryTestsс подменой культуры наru-RU. - В UITK нет
::before/::after. Уровень строки лога поэтому показывает левая кромка (border-left-color), а не точка-маркер: маркер требовал бы второго элемента в каждой строке, то есть вдвое больше элементов на двухсотстрочный буфер. - Шрифты проекта —
UnityEngine.TextCore.Text.FontAsset, а неTMPro.TMP_FontAsset. Загрузка существующего SDF как TMP-типа возвращает null, иcreationSettingsу TextCore-версии недоступен — параметры читаются черезfaceInfo/atlas*. Создавать новый шрифт:FontAsset.CreateFontAsset+AddObjectToAssetдля материала и атласа +SaveAssetIfDirtyвместоSaveAssets(последний унёс бы несохранённое у соседних сессий). - Дубль имени команды — исключение, а не «последний победил». Тихое замещение выключило бы часть команд молча.
Владелец правды: Assets/_Project/Scripts/Core/DevConsole/ (реестр, аргументы, хвост логов),
Assets/_Project/Scripts/UI/DevConsole/DevConsoleScreen.cs (экран), секция .gm-console* в
Assets/_Project/UI/Theme/components.uss; тест DevConsoleRegistryTests. Скоуп трека и приёмка —
docs/ui-architecture-rework-plan.md §Трек К.