【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;或者从不同的角度看待问…

USACO 1月比赛 铜组题解

比赛链接&#xff1a;http://usaco.org/ 第一题&#xff1a;MAJORITY OPINION 标签&#xff1a;思维、模拟题意&#xff1a;给定一个长度为 n n n的序列 a a a&#xff0c;操作&#xff1a;若区间 [ i , j ] [i,j] [i,j]内某个数字 k k k出现的次数 大于区间长度的一半&#…

已解决解决java.util.concurrent.BrokenBarrierException异常的正确解决方法,亲测有效!!!

已解决解决java.util.concurrent.BrokenBarrierException异常的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 目录 问题分析 报错原因 解决思路 解决方法 总结 在并发编程中&#xff0c;CyclicBarrier是Java提供的一个同步辅助工具类&#xff…

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

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

C语言中的数组操作技巧:提升程序的效率和可读性

1. 概念 数组是C语言中常见且重要的数据结构&#xff0c;在许多应用中都被广泛使用。合理地处理数组操作可以提高程序的效率和可读性。本文将介绍C语言中常用的数组操作方法和技巧&#xff0c;帮助读者优化数组操作并提升程序效果。 2.常用的数组操作方法 2.1 数组的初始化 C…

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

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

hyperf 二十四 模型缓存

教程&#xff1a;Hyperf 一 安装及配置 1.1 安装 目前仅支持redis。 composer require hyperf/model-cache 1.2 配置 配置位置&#xff1a;config/autoload/databases.php 配置类型默认值备注handlerstringHyperf\ModelCache\Handler\RedisHandler::class无cache_keystri…

python时间格式数据处理。

由于编码和格式问题&#xff0c;有时候从read_csv或者read_excel读取到的时间类型是不确定的。 1.字符串转datetime.datetime时间格式 如果是字符串string类型&#xff0c;则可以使用&#xff1a; df[PDATE] pd.to_datetime(df[PDATE]).dt.date 转换为date格式&#xff0c…

开发安全之:Header Manipulation

Overview 方法 echo_json() 包含未验证的数据&#xff0c; 这会招致各种形式的攻击&#xff0c;包括&#xff1a;cache-poisoning、cross-site scripting、cross-user defacement、page hijacking、cookie manipulation 或 open redirect。 Details 以下情况中会出现 Header …

Websocket基本用法

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

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

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

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

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

【零基础学习CAPL】——CAN报文的发送(配合Panel面板单次发送)

🙋‍♂️【零基础学习CAPL】系列💁‍♂️点击跳转 文章目录 1.概述2.面板创建2.1.新建一个Panel2.2. 在Panel中调出控件窗口2.3.控件添加与配置3.系统变量创建4.系统变量与Panel绑定5.CAPL脚本实现6.效果1.概述 使用场景,按下面板按钮同时发送报文。 本章主要介绍 CAPL脚…

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…

分布式系统唯一ID方案

分布式系统唯一ID方案 一、引言 在当今数字化时代&#xff0c;分布式系统的发展势不可挡&#xff0c;从云服务到微服务架构&#xff0c;都凸显了分布式系统在构建大规模、高效的应用中的重要性。而在这个庞大而复杂的系统中&#xff0c;唯一ID的生成和管理变得至关重要。唯一…

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…