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
| Tag | Example | Result |
|---|---|---|
| <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
Import TMP Essential Resources
Window → TextMeshPro → Import TMP Essential Resources. Required for TMP to work (fonts, shaders, settings).
Create a Font Asset from a custom font
Window → TMP → Font Asset Creator → pick a .ttf, Atlas Resolution 512×512 or higher, Generate → Save.
Add a TMP Text component
UI → Text - TextMeshPro for Canvas. Add Component → TextMeshPro for World Space. Assign the Font Asset.
Use rich text in the Inspector
Leave "Enable Rich Text" on (default). Type tags directly in the Text field.
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
BasicUse 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
AdvancedTypewriter 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