Overview
When developing games and applications in Unity, the quality of the User Interface (UI) is a crucial element that directly impacts player experience. However, when using Unity's standard Text component (legacy GUIText or newer uGUI.Text), you often encounter the following issues:
- Text appears blurry or jagged: Especially in high-resolution environments or when scaling text, character edges tend to become unclear.
- Performance degradation: When displaying complex UI or large amounts of text, draw calls (rendering commands) increase, causing frame rate drops.
- Limited expression: Rich expressions like text gradients, outlines, and shadows are difficult to achieve, preventing elaborate UI designs.
TextMeshPro (TMP), Unity's official package, fundamentally solves these problems and enables professional-quality text display. This article thoroughly explains TextMeshPro's basic concepts, settings for high-quality text display, and optimization techniques for maximizing performance, all targeted at beginner to intermediate individual developers.
Basic Concept of TextMeshPro: What is SDF?
What decisively differentiates TextMeshPro from standard text components is its adoption of SDF (Signed Distance Field) technology for text rendering.
Standard text bakes fonts as bitmap images into textures. With this method, when text is enlarged, pixels are stretched, causing edges to become blurry or jagged.
On the other hand, SDF stores distance information from character outlines in textures. This allows the GPU to smoothly draw character outlines in real-time using this distance information, enabling high-resolution, crisp text display no matter how much you scale. This is the foundation of TextMeshPro's "high quality."
How to Install TextMeshPro
TextMeshPro is a standard Unity package. Open Window -> Package Manager, and install Text Mesh Pro from Unity Registry. To place it in a scene, select GameObject -> UI -> TextMeshPro - Text.
Common Pitfalls for Beginners and Solutions
1. Forgetting to Create Font Assets
TextMeshPro cannot use regular font files (.ttf or .otf) directly. You must create a dedicated Font Asset.
Pitfall: Even after placing TMP text in a scene, the font remains the default "Liberation Sans SDF," and Japanese fonts or others don't apply even when set.
Solution:
- Import the font file you want to use (e.g.,
NotoSansJP-Regular.otf) into your project. - Right-click the imported font file and select
Create->TextMeshPro->Font Asset. - Drag and drop the generated font asset into the TMP component's
Font Assetslot.
2. Missing Characters (Insufficient Atlas Size)
When using languages with many character types like Japanese or Chinese, not all characters may be included in the created font asset, causing some characters to display as "□" or "?". This is because all necessary characters aren't baked into the font asset's texture (atlas).
Solution: Review the Character Set setting when creating the font asset.
- Use Custom Character List: The most efficient method is to list only necessary characters in a text file and set it in
Custom Characters. - Use Dynamic Atlas: Setting
Atlas Population ModetoDynamicautomatically adds necessary characters to the atlas at runtime. However, be aware of performance impact and increased memory usage.
Practical C# Code Examples: Dynamic Text Manipulation and Rich Text
TextMeshPro can be easily controlled from C# scripts like standard text components, but the component type referenced is different.
1. Basic Text Updates
To manipulate TMP components, declare using TMPro; and reference TextMeshProUGUI (for uGUI) or TextMeshPro (for 3D).
using UnityEngine;
using TMPro; // Required
public class TmpTextUpdater : MonoBehaviour
{
// Attach TextMeshProUGUI component from Inspector
[SerializeField]
private TextMeshProUGUI scoreText;
private int currentScore = 0;
void Start()
{
// Set initial text
UpdateScoreText();
}
// Method to increase score and update text
public void AddScore(int amount)
{
currentScore += amount;
UpdateScoreText();
}
private void UpdateScoreText()
{
// Update text directly
scoreText.text = "Current Score: " + currentScore.ToString();
}
}
Text updates should be performed event-driven (e.g., when score changes) as much as possible, not in Update() or LateUpdate(). Per-frame text updates cause mesh rebuilding, which is a major factor in performance degradation.
2. Utilizing Rich Text Tags
One of TextMeshPro's powerful features is rich text tags similar to HTML. This allows dynamically changing text color, size, style, etc. from scripts.
using UnityEngine;
using TMPro;
public class TmpRichTextExample : MonoBehaviour
{
[SerializeField]
private TextMeshProUGUI messageText;
// Display important message with rich text
public void DisplayImportantMessage(string playerName, int damage)
{
// Using <color>, <b>, <size> tags
string richMessage = $"<color=#FF0000><b>{playerName}</b></color> took <size=150%>{damage}</size> damage!";
messageText.text = richMessage;
}
void Update()
{
// Example of dynamically changing color at runtime
// Using <alpha> tag to create blinking effect
float alpha = Mathf.Abs(Mathf.Sin(Time.time * 3f)); // Blinks between 0 and 1
messageText.text = $"<alpha=#{Mathf.RoundToInt(alpha * 255):X2}>System Message: Connection Stable";
}
}
In this example, <color=#FF0000> changes color, <b> makes bold, and <size=150%> dynamically changes size. The blinking effect using <alpha> tag is particularly an advanced expression difficult with standard text.
Performance Optimization Tips
While TextMeshPro is more performant than standard text, improper usage can harm performance.
1. Reducing Draw Calls
The biggest optimization point of TextMeshPro is that text objects using the same font asset and material can be combined into a single draw call as much as possible.
- Unify Font Assets: Thoroughly use the same font asset across the entire UI.
- Share Material Instances: Create material presets for text color, outline, etc. settings and share them across multiple text objects to reduce draw calls.
2. Avoiding Text Rebuilding
When text content changes, TextMeshPro rebuilds the text mesh. This is a high-load process.
- Minimize String Changes: For frequently updated text like score displays, optimize string generation (especially
string.Formator string concatenation) and update only when necessary. - Disable Hidden Text: For off-screen or hidden text, instead of disabling with
gameObject.SetActive(false), usetextComponent.enabled = falseto disable only the component, which excludes it from Unity's rendering pipeline and improves performance.
Summary
Adopting TextMeshPro dramatically improves UI text quality and performance in Unity projects. Here are the key points explained in this article:
- Understanding SDF Technology and Creating Font Assets: TextMeshPro's high-quality rendering is based on SDF technology, and fonts must be created and set as dedicated font assets.
- Utilizing Rich Text Tags: By dynamically using tags like
<color>,<size>,<b>from C# scripts, you can easily achieve expressive UI. - Thorough Draw Call Optimization: Sharing the same font assets and material presets across multiple text objects to minimize rendering load is essential for maintaining performance in large-scale UI.
- Optimizing Dynamic Updates: For frequently updated text like score displays, avoid per-frame updates and change text content only at necessary timings to reduce mesh rebuilding load.
Use this knowledge to take your Unity project's UI to the next level.