TMP 的超链接功能本质上是在富文本中嵌入可点击的标记区域,然后通过代码检测玩家的点击位置,精准识别被点击的链接并执行对应逻辑。下面从零开始,一步步拆解。
一、超链接语法
在 TMP 文本中,超链接使用类似 HTML 的标签语法:
text
<link="自定义ID">显示文本</link> 比如在 RPG 聊天频道里标记一件装备:
text
获得稀有装备:<link="item_1234">龙息之剑</link>! 为了增强视觉提示,通常会配合下划线或颜色标签一起使用:
text
<u><link="item_1234">龙息之剑</link></u> <color=#FFA500><link="weapon_123">传说之剑</link></color> 注意事项:
- 链接 ID 可以是任意字符串,建议用有意义的命名规则(如
item_编号、player_名字) - 标签必须正确闭合,否则会破坏整个文本块的渲染
- 文本组件的
Rich Text选项必须勾选
二、点击检测的两种实现方式
方式一:Update 轮询检测(适合简单场景)
在 Update 中检测鼠标点击,然后调用 TMP_TextUtilities.FindIntersectingLink 判断是否点中了链接:
csharp
using TMPro; using UnityEngine; public class LinkHandler : MonoBehaviour { public TMP_Text textComponent; private Camera mainCamera; void Start() { mainCamera = Camera.main; textComponent.raycastTarget = true; // 必须启用射线检测 } void Update() { if (Input.GetMouseButtonDown(0)) { // 关键:查找与鼠标位置相交的链接 int linkIndex = TMP_TextUtilities.FindIntersectingLink( textComponent, Input.mousePosition, mainCamera // 注意相机参数,见下文详解 ); if (linkIndex != -1) { TMP_LinkInfo linkInfo = textComponent.textInfo.linkInfo[linkIndex]; string linkId = linkInfo.GetLinkID(); // 拿到 "item_1234" string linkText = linkInfo.GetLinkText(); // 拿到 "龙息之剑" Debug.Log($"点击了链接:ID={linkId},文本={linkText}"); OnLinkClicked(linkId, linkText); } } } void OnLinkClicked(string id, string text) { // 根据 ID 执行不同逻辑:打开物品面板、跳转网页等 } } 方式二:IPointerClickHandler 接口(推荐,性能更好)
让脚本继承 IPointerClickHandler 接口,利用 Unity 原生 UI 事件系统,比每帧轮询更高效:
csharp
using TMPro; using UnityEngine; using UnityEngine.EventSystems; [注意: 脚本必须挂载在 TMP 的 UI 对象上,且该对象需要启用
Raycast Target。
三、Canvas 渲染模式与相机参数(最容易踩的坑)
FindIntersectingLink 的第三个参数(相机)传什么,完全取决于 Canvas 的 Render Mode:
表格
| Canvas 渲染模式 | 传入的相机参数 | 说明 |
|---|---|---|
| Screen Space - Overlay | null |
UI 渲染在最上层,不需要相机 |
| Screen Space - Camera | Canvas 绑定的 World Camera |
必须传入对应相机 |
| World Space | 场景中的主相机或指定相机 | UI 存在于 3D 世界中 |
传错相机是最常见的 Bug 来源——如果参数不对,FindIntersectingLink 永远返回 -1,点击怎么都没反应。建议测试阶段先用 Overlay 模式,相机参数直接传 null。
四、动态生成超链接文本
实际项目中,文本往往是动态拼接的。推荐用 StringBuilder 批量构建,避免频繁字符串拼接带来的 GC 开销:
csharp
using System.Text; using TMPro; using UnityEngine; public class ChatMessageBuilder : MonoBehaviour { public TMP_Text chatText; private StringBuilder linkBuilder = new StringBuilder(); public void AddItemLink(string itemName, string itemId) { linkBuilder.AppendLine($"<u><link=\"{itemId}\">{itemName}</link></u>"); } public void ApplyText() { chatText.text = linkBuilder.ToString(); linkBuilder.Clear(); } } 五、实战:物品点击查看详情完整示例
csharp
using TMPro; using UnityEngine; using UnityEngine.EventSystems; [文本内容示例:
text
玩家[<link="player_007">张三</link>]分享了装备 <color=#FF6600><link="item_2048">暗影之刃</link></color>, 点击名称即可查看详情。 六、进阶:超链接 + 图文混排
TMP 的超链接可以和 Sprite 标签结合,实现图标 + 可点击文字的混排效果:
text
点击查看 <sprite name="sword_icon"> <link="item_2048">暗影之刃</link> 调试技巧:
- 用
<size=150%>临时放大图标检查对齐 - 用
<voffset=0.5em>微调图文垂直对齐 - 在编辑器中通过 TMP Sprite Asset Creator 批量处理图标
七、常见问题排查
表格
| 问题 | 可能原因 | 解决方法 |
|---|---|---|
| 点击没反应 | 相机参数传错了 | 检查 Canvas 渲染模式,调整第三个参数 |
| 点击没反应 | Raycast Target 未启用 |
勾选 TMP 组件上的 Raycast Target |
| 点击没反应 | Rich Text 未启用 |
勾选 TMP 组件上的 Rich Text |
| 链接不显示下划线 | 没有包裹 <u> 标签 |
在 <link> 外层加 <u>...</u> |
| 多个链接点击混乱 | 文本未正确闭合标签 | 检查每个 <link> 是否有对应的 </link> |
掌握了这些,你就能在聊天系统、任务描述、物品说明等任何需要文本交互的场景里,轻松实现类似网页超链接.
