Unity3D Text使用超链接跳转事件

系列文章目录

Unity工具


文章目录

  • 系列文章目录
  • 👉前言
  • 👉一、第一种使用TextMeshPro加入超链接
  • 👉二、继承Text组件,重载OnPopulateMesh方法
  • 👉三.壁纸分享
  • 👉总结


👉前言

有时候会用到跳转的问题,所以添加一个跳转的方法,方便使用,简单记录一下
主要是两种方法,一种是使用 TextMeshPro,另一种是继承Text组件,重载OnPopulateMesh方法
大家好,我是心疼你的一切,不定时更新Unity开发技巧,觉得有用记得一键三连哦。
欢迎点赞评论哦.
下面就让我们进入正文吧 !


提示:以下是本篇文章正文内容,下面案例可供参考

👉一、第一种使用TextMeshPro加入超链接

这种就比较简单了,因为它本来就支持超链接,只需要使用标签link即可

标签类型如下:

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

TMP设置如下
TMP设置为canvas下面,创建空物体,添加TextMeshPro-Text(UI)组件即可
如果想要输入中文需要自己设置字体包要不然输入不了中文的(切记)
Text Input显示的示例:

<link="linkkkkkk"><u><#0076FF>csdn url</u></color></link>

在这里插入图片描述

效果图如下所示
在这里插入图片描述

新建脚本TMPTextLink.cs开始编写代码,代码如下:

using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;

public class TMPTextLink : MonoBehaviour, IPointerClickHandler
{
    private TextMeshProUGUI m_TextMeshPro;

    void Awake()
    {
        m_TextMeshPro = this.transform.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())
        {
            //要跟标签里面的id一致
            case "linkkkkkk":
                Debug.Log("点击了linkkkkkk的超链接");
                Application.OpenURL("https://blog.csdn.net/qq_42603590?type=blog");
                break;
        }
    }
}

最后效果自行测试吧,点击之后就会跳转到博客页面,并且会打印
在这里插入图片描述

👉二、继承Text组件,重载OnPopulateMesh方法

1.使用正则表达式获取超链接标签

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

2.新建一个LinkText.cs脚本,编辑如下 ,脚本继承Text,IPointerClickHandler
代码如下:

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>();
}
public class LinkText : 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 LinkText mHyperlinkText;


    protected override void Awake()
    {
        base.Awake();
        mHyperlinkText = GetComponent<LinkText>();
    }

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

2.新建一个空物体把LinkText组件添加进去
3.最后再写一个调用脚本LinkTextOnlick.cs也挂到这个空物体上即可
代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LinkTextOnlick : MonoBehaviour
{
    public LinkText linkText;
    void Start()
    {
        // 动态显示文本
        linkText.text = "文本测试:<a link=https://blog.csdn.net/qq_42603590>我的博客</a>";
        // 绑定事件
        linkText.onLinkClick = (info) => onclick(info);
    }

    void onclick(string info)
    {
        Debug.Log(info);
        Application.OpenURL(info);
    }
}

记得挂上去之后拖一下LinkText组件,或者在start里面写一个查找都行,看自己心情喽
之后运行点击"我的博客即可跳转链接了哦"
4.运行效果图如下
在这里插入图片描述

👉三.壁纸分享

请添加图片描述
请添加图片描述


👉总结

本次总结的就是Text实现超链接跳转,有需要会继续添加新的
如能帮助到你,就帮忙点个赞吧,三连更好哦,谢谢
你的点赞就是对博主的支持,有问题记得留言评论哦!
不定时更新Unity开发技巧,觉得有用记得一键三连哦。么么哒

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Flutter第十五弹 Flutter插件

目标&#xff1a; 1.Flutter插件是什么&#xff1f;有什么作用&#xff1f; 2.怎么创建Flutter插件&#xff1f; 一、什么是插件 在flutter中&#xff0c;一个插件叫做一个package&#xff0c;使用packages的目的就是为了达到模块化&#xff0c;可以创建出可被复用和共享的代…

关于PX4模拟机型的拓展

#多旋翼 #四旋翼&#xff08;默认&#xff09; sudo make px4_sitl gazebo #带光流的四旋翼 sudo make px4_sitl gazebo_iris_opt_flow #3DR Solo&#xff08;四旋翼&#xff09; sudo make px4_sitl gazebo_solo #Typhoon H480&#xff08;六旋翼&#xff09; sudo make px4_s…

超声波清洗机对眼镜有伤害吗?四大顶尖优品公认力作!

超声波清洗机利用超声波在液体中产生的微小气泡爆炸&#xff0c;产生强大的冲击力&#xff0c;能够深入物品的各个角落&#xff0c;有效去除油污、灰尘和细菌。与传统的手工清洗相比&#xff0c;不仅清洁效率高&#xff0c;而且能够保护眼镜不受损伤&#xff0c;特别适合清洗眼…

海纳斯 hinas 的hi3798mv100 华为悦盒 6108v9 安装wifi模块

hi3798mv100安装wifi模块 1.执行脚本 &#xff0c;执行完毕后重启服务器2. 继续执行脚本3.检查网卡驱动安装是否正确4.查看网卡安装状态5.连接wifi结尾 1.执行脚本 &#xff0c;执行完毕后重启服务器 bash <(curl -sSL https://gitee.com/xjxjin/scripts/raw/main/install_…

7km远距离WiFi实时图传模块,无人机海上无线传输方案,飞睿智能WiFi MESH自组网技术

在浩瀚无垠的海洋上&#xff0c;无人机正在开启一场前所未有的技术创新。它们不再只是天空的舞者&#xff0c;更是海洋的守望者&#xff0c;为我们带来前所未有的视野和数据。而这一切的背后&#xff0c;都离不开一项创新性的技术——飞睿智能远距离WiFi实时图传模块与无线Mesh…

链式队列算法库构建

学习贺利坚老师课程,构建链式队列算法库 数据结构之自建算法库——链队&#xff08;链式队列&#xff09;_数据结构函数链队列的算法框架有哪些-CSDN博客文章浏览阅读6.2k次&#xff0c;点赞3次&#xff0c;收藏9次。本文针对数据结构基础系列网络课程(3)&#xff1a;栈和队列…

机器学习--概念理解

知识点 一、机器学习概述 人工智能 机器学习 深度学习 学习的范围&#xff1a;模式识别、数据挖掘、统计学习、计算机视觉、语音识别、自然语言处理 可以解决的问题&#xff1a;给定数据的预测问题 二、机器学习的类型 监督学习 分类 回归 无监督学习 聚类 降维 强化…

iOS项目开发遇到问题杂项坑点记录

ios17 弹窗UIAlertController展示逻辑变化&#xff0c;单个词一行展示不下不换行&#xff08;这前版本会换行&#xff09;&#xff0c;直接截断超出部分。 UINavigationController push立刻pop会异常&#xff0c;使用用setViewCollerllers可以避免这个问题 键盘切换后立刻切页…

【React Native】measureInWindow在安卓上无法正确获取View在屏幕上的布局信息

问题描述&#xff1a; 在React Native中&#xff0c;我们可以使用measureInWindow的方式去获取一个View在屏幕中的位置信息&#xff1a; 下面这个Demo中&#xff0c;我们写了一个页面HomePage和一个列表项组件ListItemA&#xff0c;我们期望每过5s监测一次列表中每一项在屏幕中…

通过搭建 24 点小游戏应用实战,带你了解 AppBuilder 的技术原理

本文将通过一个 24 点小游戏的案例&#xff0c;详细介绍百度智能云千帆 AppBuilder 的基本技术原理和使用方法&#xff0c;帮助读者快速掌握 AI 原生应用的开发流程。 1 三步构建 AI 原生应用方法论 AI 原生应用与传统应用的最大区别是交互形态彻底的拟人化&#xff0c;通过文…

【Linux学习十八】网站管理:防火墙介绍、静态站点、动态站点、域名

1.Apache Apache官网: www.apache.org 软件包名称: httpd 服务端口:80/tcp(http) 443/tcp(https) 配置文件: /etc/httpd/conf/httpd.conf 子配置文件:/etc/httpd/conf.d/*.conf 查看被占用的端口号 netstat -tuln | grep <端口号> 解哪个程序正在使用端口 80&#xff0…

vue封装原生table表格方法

适用场景&#xff1a;有若干个表格&#xff0c;前面几列格式不一致&#xff0c;但是后面几列格式皆为占一个单元格&#xff0c;所以需要封装表格&#xff0c;表格元素自动根据数据结构生成即可&#xff1b;并且用户可新增列数据。 分类&#xff1a; 固定数据部分 就是根据数据…

docker配置redis主从复制

下载redis,复制redis.conf 主节点(6379) 修改redis.conf # bind 127.0.0.1 # 注释掉这里 protected-mode no # 改为no port 6379从节点(6380) 修改redis.conf bind 127.0.0.1 protected-mode no # 改为no port 6380 replicaof 172.17.0.2 6379 # 这里的ip为主节点容器的i…

SpringSecutrity原理

一、基于RBAC实现的权限管理通常需要涉及以下几张表&#xff1a; 1. 用户表&#xff08;user&#xff09;&#xff1a;记录系统中的所有用户&#xff0c;包括用户ID、用户名、密码等信息。 2. 角色表&#xff08;role&#xff09;&#xff1a;记录系统中的所有角色&#xff0…

【项目管理体系】代码评审规范

1完整性检查 2一致性检查 3正确性检查 4可预测性检查 5健壮性检查 6结构性检查 7可追溯性检查 8可理解性检查 9可验证性检查 软件开发全套资料获取&#xff1a;&#xff08;本文末个人名片直接获取&#xff09; 软件产品&#xff0c;特别是行业解决方案软件产品不同于一般的商品…

汽车EDI: BMW EDI项目案例

宝马集团是全世界成功的汽车和摩托车制造商之一&#xff0c;旗下拥有BMW、MINI和Rolls-Royce三大品牌&#xff1b;同时提供汽车金融和高档出行服务。作为一家全球性公司&#xff0c;宝马集团在14个国家拥有31家生产和组装厂&#xff0c;销售网络遍及140多个国家和地区。 本文主…

在Linux Ubuntu系统中使用Pascal语言

Pascal是一种结构化编程语言&#xff0c;而Free Pascal作为其现代编译器&#xff0c;不仅支持跨多种操作系统和处理器架构&#xff0c;还提供了高效的内存使用和函数重载等先进功能。Free Pascal继承了Pascal语言的核心特性&#xff0c;同时进行了扩展和优化&#xff0c;使其成…

【算法】单调队列 - 基础与应用-滑动窗口最大值

题目 给定一个数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回滑动窗口中的最大值。 思路 暴力&#xff1a;遍历一遍的过程中每次从窗口找到最大的数组&#…

Springboot 项目启动时扫描所有枚举并存入缓存(redis)

为什么这么做? 为了springboot 注解属性转换字典方便一点(使用缓存的方式在Springboot 启动时获取字典数据) 在启动时会扫描com.vehicle.manager.core.enumerate包下的所有枚举(包括类中的内部枚举),并取出对应属性以json的方式存入redis 目录结构如下: RedisUtil可以在Red…

无线领夹麦克风怎么挑选,能让声音变好听的领夹麦推荐大全

近年来&#xff0c;随着直播销售和个人视频日志&#xff08;Vlog&#xff09;的流行&#xff0c;自媒体内容创作已经成为一种文化现象。这一现象不仅改变了人们获取信息的方式&#xff0c;也极大地推动了相关音频设备的发展。无线领夹麦克风&#xff0c;以其轻巧的设计和出色的…