【Unity3D小功能】Unity3D中Text使用超链接并绑定点击事件

推荐阅读

  • CSDN主页
  • GitHub开源地址
  • Unity3D插件分享
  • 简书地址
  • 我的个人博客

大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。

一、前言

在开发中遇到了要给Text加超链接的需求,研究了实现方式,将代码和使用方法总结出来,分享一下。

二、正文

2-1、实现思路

主要有两种实现思路,一种是使用Text Mesh Pro,可以直接加入超链接,实现点击事件。

另一种,就是继承Text脚本组件,重载OnPopulateMesh方法,替换最终绘制的文本。

接下来就分别讲解如何使用。

2-2、继承Text脚本组件,重载OnPopulateMesh方法

让Text显示超链接的文本内容需要以下几步:
(1)使用正则表达式提取超链接标签及里面的内容,并保存顶点信息(点击的时候使用)
(2)将文本内容加上颜色进行标识
(3)设置监听事件,在点击的时候调用

正则表达式:

//提取以<a link=>开头,以</a>结束的内容。
<a link=([^>\n\s]+)>(.*?)(</a>)

整体代码如下:

新建一个脚本命名为HyperlinkText.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;/// <summary>
/// 超链接信息类
/// </summary>
/// 
[Serializable]
public class HyperlinkInfo
{public int startIndex;public int endIndex;public string name;public readonly List<Rect> boxes = new List<Rect>();
}
/// <summary>
/// 文本控件,支持超链接
/// </summary>
public class HyperlinkText : Text, IPointerClickHandler
{/// <summary>/// 解析完最终的文本/// </summary>private string m_OutputText;/// <summary>/// 超链接信息列表/// </summary>private readonly List<HyperlinkInfo> _mLinkInfos = new List<HyperlinkInfo>();/// <summary>/// 文本构造器/// </summary>protected static readonly StringBuilder s_TextBuilder = new StringBuilder();/// <summary>/// 超链接正则表达式/// </summary>private static readonly Regex s_HrefRegex = new Regex(@"<a link=([^>\n\s]+)>(.*?)(</a>)", RegexOptions.Singleline);/// <summary>/// 文本超链接控件/// </summary>private HyperlinkText mHyperlinkText;protected override void Awake(){base.Awake();mHyperlinkText = GetComponent<HyperlinkText>();}#region 回调事件public Action<string> onLinkClick;/// <summary>/// 点击事件检测是否点击到超链接文本/// </summary>/// <param name="eventData"></param>public void OnPointerClick(PointerEventData eventData){RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, eventData.position, eventData.pressEventCamera, out var lp);foreach (var info in _mLinkInfos){var boxes = info.boxes;for (var i = 0; i < boxes.Count; ++i){if (!boxes[i].Contains(lp)) continue;onLinkClick?.Invoke(info.name);return;}}}#endregion#region 生成超链接/// <summary>/// 重新渲染网格/// </summary>public override void SetVerticesDirty(){base.SetVerticesDirty();m_OutputText = GetOutputText(text);}/// <summary>/// 处理Text顶点数据/// </summary>/// <param name="toFill"></param>protected override void OnPopulateMesh(VertexHelper toFill){var orignText = m_Text;m_Text = m_OutputText;base.OnPopulateMesh(toFill);m_Text = orignText;UIVertex vert = new UIVertex();// 处理超链接包围框foreach (var hrefInfo in _mLinkInfos){hrefInfo.boxes.Clear();if (hrefInfo.startIndex >= toFill.currentVertCount){continue;}// 将超链接里面的文本顶点索引坐标加入到包围框toFill.PopulateUIVertex(ref vert, hrefInfo.startIndex);var pos = vert.position;var bounds = new Bounds(pos, Vector3.zero);for (int i = hrefInfo.startIndex, m = hrefInfo.endIndex; i < m; i++){if (i >= toFill.currentVertCount){break;}toFill.PopulateUIVertex(ref vert, i);pos = vert.position;if (pos.x < bounds.min.x) // 换行重新添加包围框{hrefInfo.boxes.Add(new Rect(bounds.min, bounds.size));bounds = new Bounds(pos, Vector3.zero);}else{bounds.Encapsulate(pos); // 扩展包围框}}hrefInfo.boxes.Add(new Rect(bounds.min, bounds.size));}}/// <summary>/// 获取超链接解析后的最后输出文本/// </summary>/// <returns></returns>protected virtual string GetOutputText(string outputText){s_TextBuilder.Length = 0;_mLinkInfos.Clear();var indexText = 0;foreach (Match match in s_HrefRegex.Matches(outputText)){s_TextBuilder.Append(outputText.Substring(indexText, match.Index - indexText));string str = s_TextBuilder.ToString();char[] array = str.ToCharArray();                //把字符串转化成字符数组IEnumerator enumerator = array.GetEnumerator();         //得到枚举器StringBuilder stringBuilder = new StringBuilder();while (enumerator.MoveNext())                         //开始枚举{if ((char)enumerator.Current != ' ')         //向StringBuilder类对象添加非空格字符stringBuilder.Append(enumerator.Current.ToString());}var group = match.Groups[1];var hrefInfo = new HyperlinkInfo{startIndex = stringBuilder.Length * 4, // 超链接里的文本起始顶点索引endIndex = (stringBuilder.Length + match.Groups[2].Length - 1) * 4 + 3,name = group.Value};_mLinkInfos.Add(hrefInfo);s_TextBuilder.Append("<color=blue>");  // 超链接颜色s_TextBuilder.Append(match.Groups[2].Value);s_TextBuilder.Append("</color>");indexText = match.Index + match.Length;}s_TextBuilder.Append(outputText.Substring(indexText, outputText.Length - indexText));return s_TextBuilder.ToString();}#endregion
}

调用如下,新建脚本命名为HyperlinkLogic.cs,双击编辑代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class HyperlinkLogic : MonoBehaviour
{public HyperlinkText hyperlinkText;void Start(){// 动态显示文本hyperlinkText.text = "文本测试:<a link=https://blog.csdn.net/q764424567>[恬静的小魔龙]</a>";// 绑定事件hyperlinkText.onLinkClick = (info) => onclick(info);}void onclick(string info){Debug.Log(info);Application.OpenURL(info);}
}

运行结果:
在这里插入图片描述

2-3、使用Text Mesh Pro加入超链接

使用Text Mesh Pro就方便了,因为TMP自身支持超链接,只要使用标签link即可。

标签:

<link="id_01"></link>//超链接
<#0C86BA></color>//颜色
<u></u>//下划线

演示文本:

<link="id_01"><u><#0C86BA>Insert link text here</u></color></link>

在这里插入图片描述
新建脚本命名为TMPLink.cs,双击编辑代码:

using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;public class TMPLink : MonoBehaviour, IPointerClickHandler
{private TextMeshProUGUI m_TextMeshPro;void Awake(){m_TextMeshPro = gameObject.GetComponent<TextMeshProUGUI>();}void Start(){}public void OnPointerClick(PointerEventData eventData){int linkIndex = TMP_TextUtilities.FindIntersectingLink(m_TextMeshPro, Input.mousePosition, eventData.pressEventCamera);TMP_LinkInfo linkInfo = m_TextMeshPro.textInfo.linkInfo[linkIndex];RectTransformUtility.ScreenPointToLocalPointInRectangle(m_TextMeshPro.rectTransform, eventData.position, eventData.pressEventCamera, out var worldPointInRectangle);switch (linkInfo.GetLinkID()){case "id_01":Debug.Log("点击了id:id_01的超链接");Application.OpenURL("https://blog.csdn.net/q764424567");break;}}
}

运行点击结果:
在这里插入图片描述

三、后记

如果觉得本篇文章有用别忘了点个关注,关注不迷路,持续分享更多Unity干货文章。


你的点赞就是对博主的支持,有问题记得留言:

博主主页有联系方式。

博主还有跟多宝藏文章等待你的发掘哦:

专栏方向简介
Unity3D开发小游戏小游戏开发教程分享一些使用Unity3D引擎开发的小游戏,分享一些制作小游戏的教程。
Unity3D从入门到进阶入门从自学Unity中获取灵感,总结从零开始学习Unity的路线,有C#和Unity的知识。
Unity3D之UGUIUGUIUnity的UI系统UGUI全解析,从UGUI的基础控件开始讲起,然后将UGUI的原理,UGUI的使用全面教学。
Unity3D之读取数据文件读取使用Unity3D读取txt文档、json文档、xml文档、csv文档、Excel文档。
Unity3D之数据集合数据集合数组集合:数组、List、字典、堆栈、链表等数据集合知识分享。
Unity3D之VR/AR(虚拟仿真)开发虚拟仿真总结博主工作常见的虚拟仿真需求进行案例讲解。
Unity3D之插件插件主要分享在Unity开发中用到的一些插件使用方法,插件介绍等
Unity3D之日常开发日常记录主要是博主日常开发中用到的,用到的方法技巧,开发思路,代码分享等
Unity3D之日常BUG日常记录记录在使用Unity3D编辑器开发项目过程中,遇到的BUG和坑,让后来人可以有些参考。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/659724.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么样的评论更容易得到别人的关注

要发表吸引人的评论&#xff0c;可以注意这些个方面&#xff1a; 合适的软件&#xff1a;用DT浏览器的笔记本写文本&#xff0c;保存为图片&#xff0c;用图片的方式评论更容易得到别人的关注。 特别的观点&#xff1a;发表与众不同的观点&#xff0c;或者从不同的角度看待问…

WiFi基础知识介绍(超详细)

1.WiFi专业名词概念 AP(Access Point):无线接入点&#xff1a;这个概念特别广&#xff0c;在这里&#xff0c;用大白话说&#xff0c;你可以把CC3200当做一个无线路由器&#xff0c;这个路由器的特点不能插入网线&#xff0c;没有接入Internet&#xff0c;只能等待其他设备的链…

canvas自定义扩展方法:文字自动换行

查看专栏目录 canvas实例应用100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

Websocket基本用法

1.Websocket介绍 WebSocket是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手&#xff0c;两者之间就可以创建持久性的连接&#xff0c;并进行双向数据传输。 应用场景&#xff1a; 视频弹幕网页聊天体育实况更新股票基金…

基于OpenCV的高压电力检测项目案例

一、项目背景与目标 随着高压电力设施的日益增多&#xff0c;传统的巡检方式已无法满足现代电力系统的需求。为此&#xff0c;我们决定利用计算机视觉技术&#xff0c;特别是OpenCV库&#xff0c;开发一个高压电力检测系统。目标是实现自动化、高精度的电力设备检测&#xff0c…

P1228 地毯填补问题(葬送的芙蓉王【bushi】)

地毯填补问题 题目描述 相传在一个古老的阿拉伯国家里&#xff0c;有一座宫殿。宫殿里有个四四方方的格子迷宫&#xff0c;国王选择驸马的方法非常特殊&#xff0c;也非常简单&#xff1a;公主就站在其中一个方格子上&#xff0c;只要谁能用地毯将除公主站立的地方外的所有地…

Redis -- String 字符串, 计数命令,字符串操作

"学如逆水行舟&#xff0c;不进则退。" 目录 Redis的String字符串 常见命令 set get mget mset setnx setex psetex 计数命令 incr incrby decr decrby incrbyfloat 字符串操作 append getrange setrange strlen 小结 string内部编码 Redis…

文生图提示词:自然景观

场景描述 --自然景观 Natural Landscapes 涵盖了多种自然景观&#xff0c;可以用于精确地表达 AI 生成图像中所需的自然环境。 Mountain 山脉 River 河流 Forest 森林 Beach 海滩 Ocean 海洋 Lake 湖泊 Waterfall 瀑布 Desert 沙漠 Valley 山谷 Meadow 草地 Glacier 冰川 Cliff…

springboot137欢迪迈手机商城设计与开发

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

通过与chatGPT交流实现零样本事件抽取

1、写作动机&#xff1a; 近来的大规模语言模型&#xff08;例如Chat GPT&#xff09;在零样本设置下取得了很好的表现&#xff0c;这启发作者探索基于提示的方法来解决零样本IE任务。 2、主要贡献&#xff1a; 提出了基于chatgpt的多阶段的信息抽取方法&#xff1a;在第一阶…

6、应急响应-日志自动提取自动分析ELKLogkitLogonTracerAnolog等

用途&#xff1a;个人学习笔记&#xff0c;欢迎指正 目录 背景: 一、日志自动提取-七牛Logki&观星应急工具 1、七牛Logkit: (支持Windows&Linux&Mac等) 2、观星应急工具(只支持Windows) 二、日志自动分析-Web-360星图&Goaccess&ALB&Anolog 1、W…

uniapp 使用canvas 画海报,有手粘贴即可用(拆成组件了,看后面)

1.直接使用 html部分 <view click"doposter">下载海报</view> <canvas canvas-id"myCanvas" type2d style"width: 370px; height: 550px;opcity:0;position: fixed;z-index:-1;" id"myCanvas" />js 部分 drawBac…

【网络安全|漏洞挖掘】ChatGPT 再曝安全漏洞,被指泄露私密对话

风靡全球的聊天机器人 ChatGPT 近日再次陷入安全风波&#xff0c;被曝泄露用户同机器人的私密对话&#xff0c;其中包含用户名、密码等敏感信息。 ArsTechnica 网站援引其读者提供的截图报道称&#xff0c;ChatGPT 泄露了多段非用户本人的对话内容&#xff0c;包含了大量敏感信…

前端入门第二天

目录 一、列表、表格、表单 二、列表&#xff08;布局内容排列整齐的区域&#xff09; 1.无序列表&#xff08;不规定顺序&#xff09; 2.有序列表&#xff08;规定顺序&#xff09; 3.定义列表&#xff08;一个标题多个分类&#xff09; 三、表格 1.表格结构标签 2.合并…

使用宝塔面板访问MySQL数据库

文章目录 前言一、安装访问工具二、查看数据库总结 前言 前面我们已经部署了前后端项目&#xff0c;但是却不能得到数据库的信息&#xff0c;看有谁再使用你的项目。例如员工、用户等等。本次博客进行讲解如何在宝塔面板里面访问MySQL数据库。 一、安装访问工具 1、打开软件商…

TensorFlow2实战-系列教程13:Resnet实战1

&#x1f9e1;&#x1f49b;&#x1f49a;TensorFlow2实战-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Jupyter Notebook中进行 本篇文章配套的代码资源已经上传 Resnet实战1 Resnet实战2 Resnet实战3 1、残差连接 深度学习中出现了随着网络的堆叠…

scienceplots绘图浅尝

前言 科研写作中&#xff0c;黑压压的文字里面如果能有一些优美的图片无疑会给论文增色不少&#xff0c;绘图的工具有很多&#xff0c;常用的有Excel、Python、Matlab等&#xff0c;Matlab在绘图方面相较于Python有一种更加原生的科研风&#xff0c;而且可视化编辑图例、坐标轴…

ManticoreSearch-(安装配置,集群搭建)-学习总结

ManticoreSearch-(安装配置)-学习总结 基础概念安装搭建集群搭建(基于K8S) 原文地址 https://blog.csdn.net/liuyij3430448/article/details/135955025 基础概念 Manticore Search是一个专门为搜索设计的多存储数据库&#xff0c;具有强大的全文搜索功能&#xff0c;适用于…

【SparkML系列3】特征提取器TF-IDF、Word2Vec和CountVectorizer

本节介绍了用于处理特征的算法&#xff0c;大致可以分为以下几组&#xff1a; 提取&#xff08;Extraction&#xff09;&#xff1a;从“原始”数据中提取特征。转换&#xff08;Transformation&#xff09;&#xff1a;缩放、转换或修改特征。选择&#xff08;Selection&…

15.Golang中的反射机制及应用

目录 概述实践基本应用复杂应用 结束 概述 Golang中的反射用法还是比较简单的 reflect.TypeOf(arg)reflect.ValueOf(arg) 实践 基本应用 package mainimport ("fmt""reflect" )func reflectNum(arg interface{}) {fmt.Println("type ", re…