Unity中UGUI的Text实现超链接点击的解决方案

这篇具有很好参考价值的文章主要介绍了Unity中UGUI的Text实现超链接点击的解决方案。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

功能简介:

1、同一个Text内可以实现多个不同字符区域的点击;
2、适配了中文、英文、韩文、日文、阿拉伯语等,更多语种待测试;

C#脚本:

/******************************************************************
** 文件名:  UIText_Link.cs
** 版  权:  (C)  
** 创建人:  Summer
** 日  期:  2022/3/2
** 描  述:  超链接文本         
*
    "<a i=id>%s</a>"
*******************************************************************/
using System;
using UnityEngine;
using System.Text;
using UnityEngine.UI;
using System.Collections;
using UnityEngine.EventSystems;
using System.Collections.Generic;
using System.Text.RegularExpressions;

public class Text_Link : Text, IPointerClickHandler
{
    protected override void Awake()
    {
        Set_TextLinkFuncCB((string i) =>
        {
            Debug.Log($"点击了:{i}");
        });
    }
    /// <summary>
    /// 解析完最终的文本
    /// </summary>
    private string m_OutputText;

    /// <summary>
    /// 超链接信息列表
    /// </summary>
    private readonly List<HrefInfo_> m_HrefInfos = new List<HrefInfo_>();

    /// <summary>
    /// 文本构造器
    /// </summary>
    protected static readonly StringBuilder s_TextBuilder = new StringBuilder();

    /// <summary>
    /// 超链接正则
    /// </summary>
    private static readonly Regex s_HrefRegex =
        new Regex(@"<a i=([^>\n\s]+)>(.*?)(</a>)", RegexOptions.Singleline);

    //
    private static readonly Regex s_VertexFilter = new Regex(@"(|[ \n\r\t]+)", RegexOptions.Singleline);

    VertexHelper _toFill = null;
    /// <summary>
    /// 是否使用超链接  默认未False
    /// </summary>
    bool bool_IsLink = false;

    private Action<string> linkFunc_Cb = null;

    private RectTransform rect_Parent;
    private RectTransform Rect_Parent
    {
        get
        {
            if (rect_Parent == null)
            {
                Transform trans = this.transform.parent != null ? this.transform.parent.transform : this.transform;
                rect_Parent = trans.GetComponent<RectTransform>();
            }

            return rect_Parent;
        }
    }

    //设置 文本 超链接的点击回调事件
    public void Set_TextLinkFuncCB(Action<string> linkFunc_Cb)
    {
        bool_IsLink = true;
        if (this.linkFunc_Cb != null)
        {
            this.linkFunc_Cb = null;
        }
        this.linkFunc_Cb = linkFunc_Cb;
        OnPopulateMesh(_toFill);
    }

    //字符顶点数
    const int perCharVerCount = 4;

    /// <summary>
    /// 文本构造器
    /// </summary>
    protected static readonly StringBuilder textRebuild = new StringBuilder();

    protected override void OnPopulateMesh(VertexHelper toFill)
    {
        if (toFill == null)
        {
            return;
        }
        _toFill = toFill;
        //TODO 编辑器状态下这里不执行, 方便调试看到效果用
        if (!bool_IsLink)
        {
            m_Text = GetOutputText_Nomal(text);
            base.OnPopulateMesh(toFill);
            return;
        }

        var orignText = m_Text;
        m_OutputText = GetOutputText_Init(text);
        m_Text = m_OutputText;
        text = m_OutputText;
        base.OnPopulateMesh(toFill);
        m_Text = orignText;
        GetOutputText(text, toFill.currentVertCount);

        UIVertex vert = new UIVertex();

        // 处理超链接包围框
        foreach (var hrefInfo in m_HrefInfos)
        {
            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);
            Vector3 previousPos = 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 ((i - hrefInfo.startIndex) % 4 == 1)
                {
                    previousPos = pos;
                }
                if (previousPos != Vector3.zero && (i - hrefInfo.startIndex) % 4 == 0 && pos.x < previousPos.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));
        }


        if (this.gameObject.activeInHierarchy)
        {
            StartCoroutine(RefrehLayout());
        }
    }

    IEnumerator RefrehLayout()
    {
        yield return new WaitForEndOfFrame();
        LayoutRebuilder.ForceRebuildLayoutImmediate(Rect_Parent);
    }

    //初始化超链接文本 获取最终结果的定点数用
    string GetOutputText_Init(string outputText)
    {
        s_TextBuilder.Length = 0;
        m_HrefInfos.Clear();
        var indexText = 0;
        foreach (Match match in s_HrefRegex.Matches(outputText))
        {
            s_TextBuilder.Append(outputText.Substring(indexText, match.Index - indexText));
            s_TextBuilder.Append("<i><b><color=#f49037>");  // 超链接颜色

            s_TextBuilder.Append(match.Groups[2].Value);
            s_TextBuilder.Append("</color></b></i>");
            indexText = match.Index + match.Length;
        }
        s_TextBuilder.Append(outputText.Substring(indexText, outputText.Length - indexText));
        return s_TextBuilder.ToString();
    }

    /// <summary>
    /// 获取超链接解析后的最后输出文本
    /// </summary>
    /// <returns></returns>
    string GetOutputText(string outputText, int currentVertCount)
    {
        s_TextBuilder.Length = 0;
        m_HrefInfos.Clear();
        var indexText = 0;
        int vertCount = Regex.Replace(Regex.Replace(outputText.ToString(), @"\s", ""), @"<(.*?)>", "").Length * 4;
        int vercCount_Offset_Start = 0;
        int vercCount_Offset_End = 0;
        bool isLineCup = false;
        if (currentVertCount > vertCount)
        {
            isLineCup = true;
            vercCount_Offset_Start = 80;
            vercCount_Offset_End = 88;
        }
        foreach (Match match in s_HrefRegex.Matches(outputText))
        {
            s_TextBuilder.Append(outputText.Substring(indexText, match.Index - indexText));
            int offset_Len = 0;
            if (isLineCup)
            {
                offset_Len = (s_TextBuilder.Length - Regex.Replace(s_TextBuilder.ToString(), @"<(.*?)>", "").Length) * 4;
            }

            s_TextBuilder.Append("<i><b><color=#f49037>");  // 超链接颜色

            var str = Regex.Replace(s_TextBuilder.ToString(), @"\s", "");
            var group = match.Groups[1];
            var hrefInfo = new HrefInfo_
            {
                startIndex = Regex.Replace(str, @"<(.*?)>", "").Length * 4 + vercCount_Offset_Start + offset_Len, // 超链接里的文本起始顶点索引
                endIndex = (Regex.Replace(str, @"<(.*?)>", "").Length +
                Regex.Replace(Regex.Replace(match.Groups[2].ToString(), @"\s", "")
                , @"<(.*?)>", "").Length - 1) * 4 + 3 + vercCount_Offset_End + offset_Len,
                name = group.Value
            };
            m_HrefInfos.Add(hrefInfo);
            //Debug.Log($"顶点信息,开始的:{hrefInfo.startIndex},结束的:{hrefInfo.endIndex}");

            s_TextBuilder.Append(match.Groups[2].Value);
            s_TextBuilder.Append("</color></b></i>");
            indexText = match.Index + match.Length;
        }

        s_TextBuilder.Append(outputText.Substring(indexText, outputText.Length - indexText));
        return s_TextBuilder.ToString();
    }

    //获取祛除掉超链接 保留普通文本  保证配置里超链接标签的文本  在其他地方也可以正常使用,只有调用了超链接初始化的  才会给超链接形式的文本
    string GetOutputText_Nomal(string outputText)
    {
        s_TextBuilder.Length = 0;
        m_HrefInfos.Clear();
        var indexText = 0;
        MatchCollection matchs = s_HrefRegex.Matches(outputText);
        if (matchs.Count <= 0)
        {
            return outputText;
        }
        foreach (Match match in matchs)
        {
            s_TextBuilder.Append(outputText.Substring(indexText, match.Index - indexText));
            s_TextBuilder.Append(match.Groups[2].Value);
            indexText = match.Index + match.Length;
        }
        s_TextBuilder.Append(outputText.Substring(indexText, outputText.Length - indexText));
        return s_TextBuilder.ToString();
    }

    public void OnPointerClick(PointerEventData eventData)
    {
        Vector2 lp;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(
            rectTransform, eventData.position, eventData.pressEventCamera, out lp);

        foreach (var hrefInfo in m_HrefInfos)
        {
            var boxes = hrefInfo.boxes;
            for (var i = 0; i < boxes.Count; ++i)
            {
                if (boxes[i].Contains(lp))
                {
                    //Debug.Log("技能 超链接 点击了:" + hrefInfo.name);
                    linkFunc_Cb?.Invoke(hrefInfo.name);
                    return;
                }
            }
        }
    }
}
/// <summary>
/// 超链接信息类
/// </summary>
class HrefInfo_
{
    public int startIndex;

    public int endIndex;

    public string name;

    public readonly List<Rect> boxes = new List<Rect>();
}

使用方法

1、文本框内使用富文本,见截图

2、要使该文本的超链接功能生效,调用即可:

        Set_TextLinkFuncCB((string i) =>
        {
            Debug.Log($"点击了:{i}");
        });

可以设置回调的灵活性就比较高了,各位自己扩展

Demo工程内截图

ugui 文本超链接,unity,c#,游戏开发

Demo地址:

https://github.com/Panda0000000000000/TextLink.git文章来源地址https://www.toymoban.com/news/detail-721911.html

到了这里,关于Unity中UGUI的Text实现超链接点击的解决方案的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity实用功能之UGUI的Text实现颜色渐变详解 Unity3D

    在Unity3D中,UGUI是一种用于创建用户界面的强大工具。其中的Text组件用于显示文本内容,而通过实现颜色渐变效果,可以使文本更加生动和吸引人。本文将详细介绍如何在Unity中使用UGUI的Text组件实现颜色渐变效果,并提供相应的源代码。 首先,我们需要创建一个空的GameObj

    2024年02月02日
    浏览(57)
  • Android WebView H5视频播放实现全屏播放功能、全屏按钮不显示、灰显、点击无效问题解决方案

    打开硬件加速(3.0以上版本支持) set一个WebChromClient,实现onShowCustomView() 方法和onHideCustomView()方法 全屏支持 打开硬件加速 在Manifest中,对应的Activity添加: android:hardwareAccelerated = “true”。 防止h5重新加载:Manifest中,对应的Activity添加: android:configChanges=“keyboardHidden|orientation|s

    2024年02月09日
    浏览(67)
  • Unity Text 实现图文混排和超链接功能

    unity 已经在2021版本使用了全面使用了TMP实现图文混排和超链接这两个功能。由于当前项目并没有使用TMP。所以需要基于Text实现这两个功能,但是在2019之后的版本,Text 生成顶点时不再储存富文本信息顶点,所以很多以前的图文混排和超链接的插件都失效了,于是研究了一下结

    2024年02月15日
    浏览(42)
  • 小程序按钮重复点击解决方案

    小程序是直面用户便捷的应用,而在用户使用时往往都会涉及到关键节点的按钮点击,例如,注册登录时,页面跳转时,发送验证码时,付钱还款,弹出提示等等。。。如果没有控制好按钮重复点击的问题,那么影响用户体验。当然有时候也会被同行吐槽,这人不行。。。

    2024年02月13日
    浏览(42)
  • uniapp小程序ucharts点击穿透和点击位置偏移解决方案

    加上这些,完美解决 问题如标题,解决办法是在微信小程序中添加 inScrollView=\\\"true\\\"属性。 另说明:canvas2d=\\\"true\\\"作用,开启canvas2d渲染模式,需要与canvas-id=\\\"xxx\\\" 一起使用。 如不开启会存在图表层级过高,不跟随页面滑动等问题。

    2024年02月16日
    浏览(71)
  • 最强开源Text2SQL大模型本地部署的解决方案

      大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的

    2024年02月08日
    浏览(37)
  • java超简单实现文档在线预览功能,支持word\excel\text\pdf\图片等格式转pdf,aspost 转pdf部署linux中文乱码解决方案

    一、背景         在工作中需要对上传到服务器的各种类型包括但不限于word、pdf、excel等文件进行在线预览,前端比较菜搞不定,只能本人亲自上。         网上的经验比较多也比较乱, 有的只有预览,没有文件格式转换,有的也不说linux存在字体问题, 本文会直白的给

    2024年04月10日
    浏览(147)
  • unity UGUI源码分析(4)Text与TextMeshPro

    这一篇博客用于分析Text的内容的更新机制,并分析text mesh pro。 首先我们分析Text的文字是如何渲染出来的。   PupulateWithErrors方法会根据字符串生成顶点数据。其实Text会根据所给定的字符串生成相关的图集,然后对图集进行采样就可以渲染出文字了。由于TextGenerator没有开源,

    2023年04月22日
    浏览(41)
  • http请求头Content-Type的值为text/plain报错415解决方案

    问题描述:http请求报错415,经过了解主要是请求头Content-Type的值为text/plain,为了方便演示,创建一个测试类 测试类 如果请求的请求头是text/plain,则会报错,错误码415 具体报错 解决方案很简单,直接用字符串接收参数就行,示例代码

    2024年02月15日
    浏览(60)
  • Unity UGUI的Text(文本)组件的介绍及使用

    UGUI(Unity Graphic User Interface)是Unity引擎的一套用户界面系统,而Text(文本)组件是UGUI中用于在游戏界面中显示文本的组件。该组件可以用于显示游戏中的文字、数字、标签等信息。 使用UGUI的Text组件可以在游戏界面中实时显示文字信息,方便玩家了解游戏的状态、交互信息

    2024年02月12日
    浏览(68)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包