Straight answers about build size, fonts, the glyph atlas and runtime performance — distilled from real developer questions.
No. UniText doesn't bake per-font texture atlases into your build. Glyphs are rasterized at runtime into a shared atlas (Texture2DArray-based) with per-glyph reference counting and LRU eviction. Only the font data ships in your build — never atlases. On top of that, built-in Font Compression (Zstd, level 22) shrinks font data by up to ~2.7× for Latin/Arabic (CJK is more modest, ~1.3×).
No. The UniTextFont asset embeds the font bytes inside itself. The reference to the source font is Editor-only (wrapped in #if UNITY_EDITOR) — it simply doesn't exist in a player build, so it's not a runtime dependency and won't be pulled into an AssetBundle through dependency lookup. You can delete the .ttf once the asset is created.
No. You can build a UniTextFont from a .ttf located anywhere on your disk via the UniText tool window (the file dialog reads the bytes directly). Importing the font into the project is optional.
• WebGL: an empty build is ≈ 6–10 MB (it varies by Unity version and installed packages); UniText adds its native libraries (HarfBuzz, FreeType). These are the same industry-standard libs Unity's own UI Toolkit Advanced Text Generator ships — nothing exotic (UniText just carries its own copies). • Android: an APK with two architectures carries both — about +4 MB per architecture. But when you publish an AAB, Google Play delivers a device-specific bundle, so the user downloads only their own architecture (~4 MB), not both.
With TMP in Static atlas-population mode, baking the full glyph set of a typical CJK font bloats the build by tens to hundreds of MB (several 4096²/8192² atlases; expect ~80–250 MB depending on glyph count and resolution). The key point: UniText's overhead doesn't scale with glyph count — it's the same few MB whether you ship Latin or full CJK.
Yes — that's on the developer's side, and UniText doesn't get in the way. Download the font bytes with your own code (UnityWebRequest) and build a UniTextFont from them at runtime via CreateFontAsset(byte[]). To trim a font down to just the characters you need (subsetting), use UniText's build-time tool. There is no built-in CDN auto-loader in the package — that's deliberately the project's responsibility, not the engine's.
Glyphs live in tiles of three sizes — 64, 128, 256 — and the size is chosen from contour complexity (many segments → 128/256, a simple contour → 64). • SDF Detail is a multiplier on the complexity estimate. Raise it and an already non-trivial glyph is more likely to move up to a larger tile. (A genuinely simple shape stays at 64 — the multiplier only affects glyphs above the threshold.) • Tile Size Offset is a hard step along the size ladder (chosen 64 + offset 1 → 128; range −2..+2).
Only when a glyph isn't already in the atlas — never per frame. For “Hello world” it rasterizes the unique glyphs H e l o w r d. A second H does nothing; an a rasterizes just the a.
The cost is proportional to the number of unique, first-seen glyphs rasterized that frame — not to the length of the text. In our benchmark ~2000 unique glyphs on the first frame is ≈ 1 second on a typical Android device; TMP and UI Toolkit take 10+ seconds in the same scenario. Reusing cached glyphs is free.
UniText barely relies on the Unity Job System on the hot path — by design. Glyph rasterization (our proprietary lpSDF / lpMSDF) runs on the GPU via a compute shader by default; Burst jobs are only the CPU fallback when compute isn't available. The main multithreading — shaping, layout, mesh generation — runs on UniText's own OS-thread pool (not Unity Jobs, which is why they don't show up in the Jobs profiler). So “no UniText job” doesn't mean “threads are off”: either the work went to the GPU, or the atlas is already warm, or the text is below the parallelism threshold (short or single labels are processed sequentially — it's cheaper that way).
“Update() is slow” is a myth for release builds. The overhead of the magic-method call from native code is real but negligible (~1000 calls ≈ 0.16 ms) — it's not the bottleneck. The real cost in naive code is AoS memory layout, not the callback itself; UniText applies SoA where it matters (Unicode attributes, metrics, per-pixel buffers). (This is also why ECS is fast — because of SoA, not “ECS magic”.) And UniText is centralized anyway — just not as a MonoBehaviour manager: Update() itself is nearly empty, and the heavy work is gathered into a single batched pass on Canvas render callbacks (which is also what gives cross-component parallelism).
Ask in our Discord — questions like these are exactly what shaped this page, and we usually reply fast.