一、需求和尝试
今天遇到这样一个需求:在文本中插入超链接,且这个链接可以点击跳转对应的url,具体形式如下图所示。
其实这个有一个简单粗暴的方法,就是把需要加超链接的文本单独拿出来,和其他文本进行拼接,然后在需要加超链接的文本上添加点击事件。但是这样做会对文本适配有很大考验,且文本变换或者修改了,就要重新调整文本的布局。最最关键的是,这种方法对于游戏需要多语言的没有用,因为文本的长短会随着语言变化而动态进行变化,所以这种方法还是pass。
二、解决方案
找了一遍网上的文档,其中不少用Text组件去做的,这种方法确实可以实现文本中添加点击效果跳转超链接,但是当一个文本中有多个超链接时,就会只响应一个,或者点击一个,然后所有点击事件全部响应,没法实现我们需要的效果。
最终确定的方法就是使用TextMeshPro组件来实现
首先unity官方的TextMeshPro组件富文本中就可以添加超链接,其所有富文本标签效果在下面,最后有超链接添加方法
<b>粗体标签</b>
<i>斜体标签</i>
<u>下划线标签</u>
<s>删除线标签</s>
<sup>上标标签</sup>前面后面上标签 5<sup>。</sup>C
<sub>下标标签,如:</sub>H<sub>2</sub>O
<size=48>文字大小</size>
<size=55%>文字大小-百分比</size>
<size=+18>默认大小上再增加文字大小</size>
<size=-18>默认大小上减去指定文字大小</size>
<pos=40>距离左侧的缩进,可以实现类似首行缩进的,文字大小不同这个值缩进程度不同
<color=yellow>颜色标签写法一</color>
<#00ff00>颜色标签写法二</color>
<alpha=#FF>正 <alpha=#CC>在 <alpha=#AA>进 <alpha=#88>行 <alpha=#66>透 <alpha=#44>明度 <alpha=#22>的 <alpha=#00>变化
<alpha=#FF>
<align="left">左对齐<sprite=2>也是默认对齐</align>
<align="center">居中对齐<sprite=2></align>
<align="right">右对齐<sprite=5></align>
1. <indent=15%>缩进15%.
多行有效</indent>
2. <indent=100>缩进100像素
多行有效</indent>
3. <indent=5em>缩进5em
多行有效</indent>
4. <indent=15%>缩进15%.
<cspace=1em>1em字体单位间距</cspace>
<cspace=10>10像素字体单位间距</cspace>
<cspace=-4>-10像素缩小间距
使用 <font="LiberationSans SDF">different font?</font>或者使用<font="YouYuan SDF" material="YouYuan SDF - Outline">不同材质?
<line-height=50%>50%行间距
行间距</line-height>
<line-height=100%>100%行间距
正常</line-height>
<line-height=150%>
150%
行间距</line-height>
<line-indent=15%>行缩进只影响单行显示,多行不受影响</line-indent>
<lowercase>ABCDEFG</lowercase>
<uppercase>ABCDEFG</uppercase>
<smallcaps>AbcdeFg</smallcaps>
设置 <mark=#ff0000aa>标注</mark> 前面是标注,需要透明度
<noparse><b></noparse> 取消标签的作用,如b加粗没效果
<style=H1>内置</style><style=H2>的</style><style=C1>样式名</style>
<width=50%>设定高可用宽度,超出后即使没换行会自动换行的</width>
<link="https://blog.csdn.net/qq_41789645?spm=1010.2135.3001.5421">网站,需要额外脚本</link>
上面需求中的文本形式如下图
其中需要添加一个LinkOpener脚本,来监听点击事件,脚本在下面
using TMPro;
using UnityEngine.EventSystems;
using UnityEngine;[RequireComponent(typeof(TMP_Text))]public class LinkOpener : MonoBehaviour, IPointerClickHandler
{public void OnPointerClick(PointerEventData eventData){TMP_Text pTextMeshPro = GetComponent<TMP_Text>();//int linkIndex = TMP_TextUtilities.FindIntersectingLink(pTextMeshPro, eventData.position, null); // If you are not in a Canvas using Screen Overlay, put your camera instead of nullint linkIndex = TMP_TextUtilities.FindIntersectingLink(pTextMeshPro, eventData.position, Camera.main);if (linkIndex != -1){TMP_LinkInfo linkInfo = pTextMeshPro.textInfo.linkInfo[linkIndex];Application.OpenURL(linkInfo.GetLinkID());}}
}
需要注意的是,上面脚本的
int linkIndex = TMP_TextUtilities.FindIntersectingLink(pTextMeshPro, eventData.position, Camera.main);
这一行中,如果你的canvas设置为Screen Overlay,则该方法最后传入null,但是如果你的canvas中用的Screen Space Camera,则该方法最后传入你的uicanvas中的camera,否则点击文本的位置计算错误,就会导致文本无法点击。
最后需要注意的就是,TextMeshPro中用到的字体是需要单独制作的,通常默认的字体只会有英文,如果需要添加中文或者其他语言,则需要自己单独制作字体文件
三、TextMeshPro字体文件的制作
TextMeshPro插件中自带文本的制作,下面是制作过程
打开FontAssetCreator,就是下图所示,根据自身需求,填写其中的参数,点击制作就好了,然后点击保存到项目的文件夹中即可
我这边制作出来的字体文件有个小问题,就是TextMeshPro使用我自己做出来的字体,显示出来的效果,永远没有他默认的字体效果好,文本会有毛边之类的,修改shader后会有所改善,但是还是没法达到默认字体或者官方提供字体的效果,有知道原因的大神欢迎解答一下。
针对上面这个问题,我发现TextMeshPro的字体可以追加额外字符,就是在字体不变的基础上,添加额外的文本,这样就可以不替换原来的字体文件了
就是找到TMP Settings或者直接找到那个SDF字体文件,会发现有个Fallback Font Assets的属性,点击加号就可以继续添加额外的SDF字体库资源文件。
如下图所示
over~
看到这里了,点个赞再走吧,你的认可就是我创作的动力~