Поддержка

Часто задаваемые вопросы

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

Размер билда и распространение

Раздувает ли UniText размер билда? Что на самом деле попадает в билд?

Нет. UniText не запекает текстурные атласы под каждый шрифт в билд. Глифы растеризуются в рантайме в общий атлас (на базе Texture2DArray) с подсчётом ссылок на каждый глиф и вытеснением по LRU. В билд попадают только данные шрифта — атласы никогда. Вдобавок встроенное сжатие шрифтов (Zstd, уровень 22) уменьшает данные шрифта до ~2.7× для латиницы и арабского (для CJK скромнее, ~1.3×).

Нужно ли хранить и поставлять файлы .ttf?

Нет. Ассет UniTextFont встраивает байты шрифта внутрь себя. Ссылка на исходный шрифт существует только в редакторе (обёрнута в #if UNITY_EDITOR) — в сборке плеера её попросту нет, поэтому это не рантайм-зависимость и она не попадёт в AssetBundle через разрешение зависимостей. Файл .ttf можно удалить сразу после создания ассета.

Нужно ли вообще импортировать .ttf в проект?

Нет. UniTextFont можно собрать из .ttf, лежащего в любом месте на диске, через окно инструментов UniText (диалог выбора файла читает байты напрямую). Импорт шрифта в проект — опционален.

Сколько UniText на самом деле добавляет к пустому билду?

• WebGL: пустой билд занимает ≈ 6–10 MB (зависит от версии Unity и установленных пакетов); UniText добавляет свои нативные библиотеки (HarfBuzz, FreeType). Это те же индустриально-стандартные библиотеки, что поставляет собственный Advanced Text Generator из UI Toolkit в Unity — ничего экзотического (UniText просто везёт собственные копии). • Android: APK с двумя архитектурами несёт обе — примерно +4 MB на архитектуру. Но при публикации AAB Google Play доставляет бандл под конкретное устройство, поэтому пользователь скачивает только свою архитектуру (~4 MB), а не обе.

Как UniText соотносится с TextMesh Pro для CJK или крупных шрифтов?

У TMP в режиме Static (заполнение атласа) запекание полного набора глифов типичного CJK-шрифта раздувает билд на десятки-сотни MB (несколько атласов 4096²/8192²; ожидайте ~80–250 MB в зависимости от количества глифов и разрешения). Ключевой момент: накладные расходы UniText не растут с количеством глифов — это те же несколько MB, поставляете ли вы латиницу или полный CJK.

Можно ли загружать шрифты динамически с сервера или CDN?

Да — это на стороне разработчика, и UniText не мешает. Скачайте байты шрифта своим кодом (UnityWebRequest) и соберите из них UniTextFont в рантайме через CreateFontAsset(byte[]). Чтобы урезать шрифт до нужных вам символов (сабсеттинг), используйте инструмент UniText на этапе сборки. Встроенного автозагрузчика с CDN в пакете нет — это намеренно ответственность проекта, а не движка.

Шрифты и системные шрифты

Может ли UniText использовать системный шрифт ОС? Чего это стоит по памяти и запуску?

Да — SystemFont читает файл шрифта напрямую из ОС в рантайме, поэтому на размер билда это никак не влияет (ничего не запекается). Разрешение шрифта ленивое (при первом использовании), поэтому запуск приложения не замедляется.

Поддерживает ли WebGL системные шрифты?

Нет — и это ограничение браузера, а не UniText. Песочница браузера не даёт доступа к шрифтам ОС. Для WebGL встройте шрифт в ассет UniTextFont (или загрузите байты сами — см. вопрос о CDN выше).

Атлас глифов — SDF Detail и Tile Size

Что на самом деле делают «SDF Detail» и «Tile Size Offset»?

Глифы живут в плитках трёх размеров — 64, 128, 256 — и размер выбирается по сложности контура (много сегментов → 128/256, простой контур → 64). • SDF Detail — это множитель для оценки сложности. Поднимите его — и уже нетривиальный глиф с большей вероятностью перейдёт на плитку побольше. (По-настоящему простая форма остаётся на 64 — множитель влияет только на глифы выше порога.) • Tile Size Offset — это жёсткий шаг по лестнице размеров (выбрано 64 + смещение 1 → 128; диапазон −2..+2).

Какой из двух приоритетнее для производительности?

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

Производительность в рантайме

Когда UniText растеризует глифы? Копирует ли он память каждый кадр?

Только когда глифа ещё нет в атласе — никогда не каждый кадр. Для «Hello world» он растеризует уникальные глифы H e l o w r d. Второй H не делает ничего; a растеризует только a.

Почему возникает кратковременный подлаг, когда сразу появляется много нового текста?

Стоимость пропорциональна числу уникальных, впервые встреченных глифов, растеризованных в этом кадре — а не длине текста. В нашем бенчмарке ~2000 уникальных глифов на первом кадре — это ≈ 1 секунда на типичном Android-устройстве; TMP и UI Toolkit в том же сценарии тратят 10+ секунд. Повторное использование закешированных глифов бесплатно.

Я не вижу задачи UniText в профайлере — многопоточность вообще работает?

UniText почти не полагается на Unity Job System на горячем пути — и это осознанно. Растеризация глифов (наши собственные lpSDF / lpMSDF) по умолчанию идёт на GPU через compute-шейдер; Burst-задачи — это лишь резервный путь на CPU, когда compute недоступен. Основная многопоточность — шейпинг, вёрстка, генерация меша — работает на собственном пуле OS-потоков UniText (не на Unity Jobs, поэтому они и не видны в профайлере Jobs). Так что «нет задачи UniText» не значит «потоки выключены»: либо работа ушла на GPU, либо атлас уже прогрет, либо текст ниже порога параллелизма (короткие или одиночные надписи обрабатываются последовательно — так дешевле).

Вредит ли MonoBehaviour.Update() производительности? Нужен ли единый UniTextManager?

«Update() медленный» — это миф для релизных билдов. Накладные расходы на вызов magic-метода из нативного кода реальны, но пренебрежимо малы (~1000 вызовов ≈ 0.16 ms) — это не узкое место. Настоящая цена в наивном коде — это раскладка памяти AoS, а не сам колбэк; UniText применяет SoA там, где это важно (атрибуты Unicode, метрики, буферы на каждый пиксель). (Именно поэтому ECS быстр — из-за SoA, а не «магии ECS».) И UniText в любом случае централизован — просто не как MonoBehaviour-менеджер: сам Update() почти пуст, а тяжёлая работа собирается в один пакетный проход на колбэках рендера Canvas (что заодно даёт параллелизм между компонентами).

Не нашли свой ответ?

Спросите в нашем Discord — именно такие вопросы и сформировали эту страницу, и мы обычно отвечаем быстро.

Вопросы?: [email protected]