Unity Term Book
Animation & UI

TextMesh Pro

TextMesh Pro is Unity's advanced text package — crisp glyphs at any size via SDF, plus rich text tags, font styles, material presets, and complex text effects.

Imagine...

The old Text component is a bitmap font — glyphs are images, so zooming blurs them. TextMesh Pro uses SDF (Signed Distance Field) — like vector graphics — each character is a math function, sharp at any size. Rich text tags work like HTML: write color=red in the string and that span turns red, no extra Text components.

The concept in detail

SDF Rendering: TextMesh Pro builds an SDF texture from a font — each pixel stores distance to the nearest glyph edge. At render time the shader reconstructs a sharp outline at any scale. One atlas can show 8px through 200px without a rebuild.

A Font Asset is the core TMP asset — SDF texture plus metadata (spacing, kerning, glyphs). Create one via: Window → TextMeshPro → Font Asset Creator. Pick a source font (.ttf/.otf), character set (ASCII, Unicode range), atlas size. Use Dynamic Atlas (2021+) to add glyphs on demand — great for CJK.

Rich Text Tags are inline markup: <b>, <i>, <color=#ff0000>, <size=24>, <sprite index=0>, <gradient>, <link=“url”>… One string can carry rich formatting — dialogue, skill tooltips, damage numbers.

TMP has two components: TMP_Text (abstract base) with TextMeshProUGUI (Canvas UI) and TextMeshPro (World Space/3D). Always reference TMP_Text so the same code works for both.

Rich Text tag reference

TagExampleResult
<b>, <i><b>Bold</b> <i>Italic</i>Bold Italic
<color><color=red>danger</color>danger
<color=#hex><color=#f97316>fire</color>fire
<size><size=20>large</size>large
<sprite><sprite="icons" name="coin">🪙 (sprite from atlas)
<link><link="item_001">Sword</link>Sword
<alpha><alpha=#88>ghost</alpha>ghost
<mark><mark=#ffff00aa>highlight</mark>highlight

Hands-on steps

1

Import TMP Essential Resources

Window → TextMeshPro → Import TMP Essential Resources. Required for TMP to work (fonts, shaders, settings).

2

Create a Font Asset from a custom font

Window → TMP → Font Asset Creator → pick a .ttf, Atlas Resolution 512×512 or higher, Generate → Save.

3

Add a TMP Text component

UI → Text - TextMeshPro for Canvas. Add Component → TextMeshPro for World Space. Assign the Font Asset.

4

Use rich text in the Inspector

Leave "Enable Rich Text" on (default). Type tags directly in the Text field.

5

Add Vietnamese/CJK characters

Font Asset Creator → Character Set → Custom Range → enter the Unicode range. Or use Dynamic Atlas Mode.

Interactive simulator

Type rich text tags to preview — similar to the TMP field in Unity's Inspector.

Preview

Code example

Basic

Use TMP_Text from script — set text, rich text, and color at runtime.

using UnityEngine;
using TMPro; // TextMesh Pro namespace

public class TMPController : MonoBehaviour
{
  // TMP_Text works for both UI and World Space
  [SerializeField] TMP_Text titleText;
  [SerializeField] TMP_Text damageText;

  public void ShowDamage(int amount, bool isCrit)
  {
      if (isCrit)
      {
          // Critical hit: gold, larger type
          damageText.text = $"<color=#fbbf24><size=1.5em><b>CRIT {amount}</b></size></color>";
      }
      else
      {
          damageText.text = $"<color=red>-{amount}</color>";
      }
  }

  public void SetTitle(string name, int level)
  {
      // TMP_Text.SetText() can be cheaper than assigning .text
      titleText.text = $"{name} <size=0.7em><color=#64748b>Lv.{level}</color></size>";
  }

  // Vertex color without tags
  public void SetColor(Color c)
  {
      titleText.color = c;
  }
}

Code example

Advanced

Typewriter effect — reveal characters one by one via a coroutine, tags included.

using UnityEngine;
using System.Collections;
using TMPro;

public class TypewriterEffect : MonoBehaviour
{
  [SerializeField] TMP_Text dialogText;
  [SerializeField] float charDelay = 0.04f;

  Coroutine current;

  public void ShowText(string text)
  {
      if (current != null) StopCoroutine(current);
      current = StartCoroutine(TypeRoutine(text));
  }

  IEnumerator TypeRoutine(string text)
  {
      dialogText.text = text;
      dialogText.ForceMeshUpdate(); // Rebuild the mesh immediately

      TMP_TextInfo info = dialogText.textInfo;
      int total = info.characterCount;

      // Hide every character via alpha
      for (int i = 0; i < total; i++)
      {
          SetCharAlpha(i, 0);
      }

      // Reveal one by one
      for (int i = 0; i < total; i++)
      {
          SetCharAlpha(i, 255);
          dialogText.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32);
          yield return new WaitForSeconds(charDelay);
      }
  }

  void SetCharAlpha(int charIdx, byte alpha)
  {
      TMP_TextInfo info = dialogText.textInfo;
      if (charIdx >= info.characterCount) return;
      int matIdx = info.characterInfo[charIdx].materialReferenceIndex;
      int vertIdx = info.characterInfo[charIdx].vertexIndex;
      Color32[] colors = info.meshInfo[matIdx].colors32;
      for (int k = 0; k < 4; k++) colors[vertIdx + k].a = alpha;
  }
}

📌 Quick recap

  • SDF: sharp text at any size from one atlas
  • TextMeshProUGUI: Canvas UI; TextMeshPro: World/3D
  • Reference TMP_Text (base) so one script covers both
  • ForceMeshUpdate() when you need textInfo immediately
  • Dynamic Atlas Mode for large character sets (Vietnamese, CJK)

⚠️ Common mistakes

  • ❌ Characters show as □ (tofu)

    The Font Asset has no glyph for that character

    ✅ Rebuild the Font Asset with a Unicode range that covers the language

  • ❌ Rich text tags do nothing

    Enable Rich Text is off on the TMP component

    ✅ Inspector → Extra Settings → Enable Rich Text = ON