TextMesh Pro Lag, CPU Spikes and GC Allocations: Causes and Fixes

Last reviewed

Short answer

TextMesh Pro gets slow when many texts change at once: every change re-parses and rebuilds the whole text on the main thread, string formatting allocates garbage, layout components and canvases rebuild around it, and new glyphs are added to the atlas mid-frame.

UniText does less work per change and spreads the rest: changed texts are processed together once per frame on worker threads, each change reruns only the pipeline stage it affects, shaping results are cached per paragraph and per word, and text can be set from a StringBuilder or a span without allocating.

Where the time goes in TextMesh Pro

  • Whole-text rebuilds. Any new value re-parses the entire text and regenerates its mesh on the main thread before the canvas renders. Layout components ask for preferred sizes, which runs another measuring pass, and Auto Size lays the text out several times until it fits; together they can multiply the passes, as Unity's TMP developer explained on Android.
  • Canvas rebuilds. A change to any element makes Unity re-analyze the whole canvas, so a ticking timer can rebuild a full HUD.
  • Garbage. Building strings every frame allocates; Unity's memory guide points to TextMesh Pro's SetText overloads instead. Those still build a string in the Editor, and reading .text back after SetText allocates one.
  • Glyphs added mid-frame. A character missing from a dynamic atlas is rasterized synchronously on the main thread when the text is parsed. Users report seconds of stalls for uncached Japanese text on low-end hardware, and the advice is to pre-bake static atlases per script.
  • UI Toolkit. Its Advanced Text Generator, announced as the default in 6.5, comes with Unity reporting 10–40% lower CPU cost than its previous text, and Unity 6.6 adds allocation-free SetText overloads. It applies to UI Toolkit, not to uGUI and TextMesh Pro.

Unity's own mitigations still apply to any UI: split canvases by how often they change, avoid layout groups where anchors will do, turn off Raycast Target on text that is not clicked, and compute Auto Size once instead of every change.

How UniText keeps text cheap

UniText and TextMesh Pro rendering the same multilingual text side by side, with each side's frame rate shown.
ChangeWork UniText reruns
Alphanone: no mesh rebuild
Colorat most the mesh, from cached glyph positions
Alignment, justificationglyph placement within the existing lines
Font size, box widthline breaking and layout, without shaping again
New textparsing and shaping, with paragraph and word caches
  • One batch per frame. A change marks the text dirty. Once per canvas update, before uGUI renders, every dirty text is processed in one pass, so several changes in a frame cost one rebuild.
  • Worker threads. Parsing, shaping and layout of all changed texts run on a pool of worker threads, one fewer than the CPU cores, together with the main thread. Unity APIs are touched only on the main thread before and after the batch.
  • Burst rasterization. New glyphs from all changed texts are collected together, rasterized by Burst jobs and uploaded before any mesh is built.
  • Shaping caches. Repeated paragraphs skip shaping entirely, and paragraphs that reuse words, such as counters, timers and chat, splice cached words instead of shaping them again.
  • No garbage from text. SetText takes a StringBuilder or a character span without allocating, and the rendered and markup-free text are read back without allocating.
csharp
readonly StringBuilder sb = new();

void Update()
{
    sb.Clear().Append("Score: ").Append(score);
    scoreText.SetText(sb);
}

Questions

Does parallel processing work on mobile and WebGL?

On devices with more than one core it does. WebGL and single-core devices process on the main thread, and parallel processing can be turned off with UniTextBase.UseParallel.

How do I find what a text costs?

The debug overlay shows pipeline statistics per text, and the processing events mark the start and end of each frame's batch for profiling.

Check it in your project

Run the browser demo, follow the setup guide, or compare the free version with the licenses.

Related problems