Unity Term Book
动画与 UI

TextMesh Pro

TextMesh Pro 是 Unity 的高级文字渲染包,通过 SDF 技术在任意尺寸下保持清晰字形,并支持富文本标签、字体样式、材质预设与复杂文字特效。它是 UI 与世界空间文字的事实标准,帮助本地化项目处理多语言排版、字体回退与图文混排需求,并让 HUD、对话气泡与伤害数字更加锐利、清晰美观。

想象一下...

旧的 Text 组件是位图字体——字形是图片,放大就会糊。TextMesh Pro 使用 SDF(Signed Distance Field)——更像矢量图——每个字符是数学函数,任意尺寸都清晰。Rich text tags 像 HTML:在字符串里写 color=red,那段就变红,无需额外 Text 组件。

概念详解

SDF Rendering:TextMesh Pro 从字体生成 SDF texture——每个像素存储到最近字形边缘的距离。渲染时 shader 在任意缩放下重建清晰轮廓。 同一 atlas 可显示 8px 到 200px,无需重建。

Font Asset 是 TMP 的核心资源——SDF 纹理加元数据 (字距、kerning、字形)。创建路径:Window → TextMeshPro → Font Asset Creator。 选择源字体(.ttf/.otf)、字符集(ASCII、Unicode 范围)、atlas 尺寸。 使用 Dynamic Atlas(2021+)可按需添加字形——适合中日韩。

Rich Text Tags 是内联标记: <b><i><color=#ff0000><size=24><sprite index=0><gradient><link=“url”>… 一条字符串即可承载丰富格式——对话、技能提示、伤害数字。

TMP 有两个组件: TMP_Text (抽象基类),以及 TextMeshProUGUI (Canvas UI)和 TextMeshPro (World Space/3D)。始终引用 TMP_Text, 同一套代码即可兼顾两者。

Rich Text 标签参考

Tag示例结果
<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)
<link><link="item_001">Sword</link>Sword
<alpha><alpha=#88>ghost</alpha>ghost
<mark><mark=#ffff00aa>highlight</mark>highlight

动手步骤

1

导入 TMP Essential Resources

Window → TextMeshPro → Import TMP Essential Resources。TMP 正常工作所必需(字体、shader、设置)。

2

从自定义字体创建 Font Asset

Window → TMP → Font Asset Creator → 选 .ttf,Atlas Resolution 512×512 或更高,Generate → Save。

3

添加 TMP Text 组件

UI → Text - TextMeshPro 用于 Canvas。Add Component → TextMeshPro 用于 World Space。指定 Font Asset。

4

在 Inspector 中使用富文本

保持 "Enable Rich Text" 开启(默认)。直接在 Text 字段输入标签。

5

添加越南语/中日韩字符

Font Asset Creator → Character Set → Custom Range → 输入 Unicode 范围。或使用 Dynamic Atlas Mode。

交互模拟器

输入富文本标签预览——类似 Unity Inspector 中的 TMP 字段。

Preview

代码示例

基础

用脚本操作 TMP_Text——运行时设置文字、富文本与颜色。

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;
  }
}

代码示例

进阶

打字机效果——用协程逐字显现,标签一并支持。

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;
  }
}

📌 快速记忆

  • SDF:同一 atlas 任意尺寸都清晰
  • TextMeshProUGUI:Canvas UI;TextMeshPro:World/3D
  • 引用 TMP_Text(基类),一套脚本兼顾两者
  • 需要立刻读 textInfo 时调用 ForceMeshUpdate()
  • 大字符集(越南语、中日韩)用 Dynamic Atlas Mode

⚠️ 常见错误

  • ❌ 字符显示为 □(豆腐块)

    Font Asset 没有该字符的字形

    ✅ 用覆盖该语言的 Unicode 范围重建 Font Asset

  • ❌ 富文本标签无效

    TMP 组件上 Enable Rich Text 关闭

    ✅ Inspector → Extra Settings → Enable Rich Text = ON