TextMeshPro (TMPro) expert for Unity text rendering with advanced typography, performance optimization, and professional text effects. Masters font asset creation, dynamic fonts, rich text formatting, material presets, and text mesh optimization. Use PROACTIVELY for text rendering, font management, localization text, UI text performance, or text effects implementation.
This skill inherits all available tools. When active, it can use any tool Claude has access to.
references/advanced-patterns.mdreferences/fundamentals.mdreferences/performance-optimization.mdTextMeshPro (TMPro) is Unity's advanced text rendering solution using Signed Distance Field (SDF) technology for resolution-independent, high-quality text with minimal performance overhead.
Foundation Required: unity-csharp-fundamentals (TryGetComponent, FindAnyObjectByType), unity-ui (UI systems, Canvas, UGUI)
Core Topics:
using TMPro;
using UnityEngine;
public class TextController : MonoBehaviour
{
[SerializeField] private TMP_Text mDisplayText;
void Start()
{
mDisplayText.text = "Hello, World!";
mDisplayText.fontSize = 36;
mDisplayText.color = Color.white;
}
}
// TMP_Text - Base class, use for serialization (works with both)
[SerializeField] private TMP_Text mText;
// TextMeshProUGUI - Canvas UI text (most common)
[SerializeField] private TextMeshProUGUI mUiText;
// TextMeshPro - 3D world space text (MeshRenderer)
[SerializeField] private TextMeshPro mWorldText;
// Basic formatting
text.text = "<b>Bold</b> and <i>Italic</i>";
text.text = "<size=48>Large</size> and <size=24>Small</size>";
text.text = "<color=#FF0000>Red</color> text";
// Advanced formatting
text.text = "<mark=#FFFF00AA>Highlighted</mark>";
text.text = "H<sub>2</sub>O and E=mc<sup>2</sup>";
text.text = "<s>Strikethrough</s> and <u>Underline</u>";
// Sprite embedding
text.text = "Score: 100 <sprite=0>";
| Scenario | Component | Reason |
|---|---|---|
| UI Canvas text | TextMeshProUGUI | Canvas integration, auto-batching |
| 3D world labels | TextMeshPro | MeshRenderer, world-space |
| Serialized reference | TMP_Text | Works with both types |
| Input field | TMP_InputField | Built-in input handling |
| Dropdown | TMP_Dropdown | Built-in dropdown UI |
Static Font Asset:
- Pre-generated character set
- Best performance (no runtime generation)
- Use for: Known character sets, optimized builds
Dynamic Font Asset:
- Runtime character generation
- Flexible but slower initial render
- Use for: Localization, user input, unknown characters
Font Asset Creator (Window > TextMeshPro > Font Asset Creator)
Sampling Point Size: Use highest size that fits atlas (better quality)
Padding: 5-9 for normal use, higher for effects (outline, glow)
// BAD: Frequent text changes trigger mesh rebuild
void Update()
{
scoreText.text = $"Score: {score}"; // Rebuilds every frame
}
// GOOD: Update only when value changes
private int mLastScore = -1;
void Update()
{
if (score != mLastScore)
{
mLastScore = score;
scoreText.text = $"Score: {score}";
}
}
// BETTER: Use SetText for formatted updates (less allocation)
void UpdateScore(int score)
{
scoreText.SetText("Score: {0}", score);
}
// Use StringBuilder for complex text construction
private readonly StringBuilder mSb = new StringBuilder(256);
void BuildComplexText()
{
mSb.Clear();
mSb.Append("Player: ");
mSb.Append(playerName);
mSb.Append(" | Score: ");
mSb.Append(score);
displayText.SetText(mSb);
}
// Prefer SetText with parameters over string interpolation
text.SetText("{0}/{1}", currentHP, maxHP); // Less GC
// Instead of
text.text = $"{currentHP}/{maxHP}"; // More GC
// Apply material preset at runtime
[SerializeField] private Material mHighlightMaterial;
[SerializeField] private Material mNormalMaterial;
void Highlight(bool active)
{
mText.fontMaterial = active ? mHighlightMaterial : mNormalMaterial;
}
// Modify material properties
mText.fontMaterial.SetFloat(ShaderUtilities.ID_OutlineWidth, 0.2f);
mText.fontMaterial.SetColor(ShaderUtilities.ID_OutlineColor, Color.black);
Core TextMeshPro concepts:
Optimization techniques:
Advanced usage patterns:
// AVOID: Creating new materials per text instance
text.fontMaterial = new Material(text.fontMaterial); // Memory leak risk
// AVOID: Updating text in Update() without change check
void Update() { text.text = score.ToString(); } // Constant rebuild
// AVOID: Excessive rich text nesting
text.text = "<b><i><color=#FF0000><size=48>...</size></color></i></b>";
// AVOID: Dynamic fonts for static content
// Use pre-generated static font assets instead