Unity Text 实现文本超链接

本文介绍了如何在Unity 2019.1.5f1及以上版本中实现Text组件的文本超链接功能,由于新版Text不再存储完整顶点信息,原有的实现方式不再适用。文章提供了一种新的代码实现方案,包括Editor扩展和使用示例。
摘要由CSDN通过智能技术生成

Unity Text 实现文本超链接

由于Unity2019.1.5f1及更高版本不再存储Text的完整vertex信息,不支持unity2019.1.5f1及更高版本,所以以前的脚本不适用新的Text。因此,重新实现文本超链接功能。

说明:

1.Text 不存储空格顶点信息
2.Text 不存储富文本顶点信息

代码:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System;
using UnityEngine.Events;
using System.Text;
using System.Text.RegularExpressions;

/// <summary>
/// Text拓展
/// </summary>
[ExecuteInEditMode]
public class UIText : Text, IPointerClickHandler
{
   

    /// <summary>
    /// 正则表达式MOI
    /// </summary>
    private static readonly string m_RegexTag = @"\<([0-9A-Za-z]+)=(.+?)(#(.+?))?((\|[0-9]+){0,2})(##(.+?))?(#color((\|[0-9A-Za-z]+){0,2}))?\/>";
    private static readonly Regex m_Regex = new Regex(m_RegexTag, RegexOptions.Singleline);
    /// <summary>
    /// 文本转换
    /// </summary>
    private static readonly StringBuilder m_TextBuilder = new StringBuilder();
    /// <summary>
    /// 顶点列表
    /// </summary>
    private readonly UIVertex[] m_TempVerts = new UIVertex[4];
    /// <summary>
    /// 输出文本
    /// </summary>
    private string m_OutputText;

    #region 超链接

    /// <summary>
    /// 是否存在超链接
    /// </summary>
    [SerializeField] protected bool isHaveHref = false;

    /// <summary>
    /// 超链接数据
    /// </summary>
    private readonly List<HrefInfo> m_HrefInfos = new List<HrefInfo>();

    /// <summary>
    /// 超链接点击事件
    /// </summary>
    [Serializable] public class HrefClickEvent : UnityEvent<string, string, string> {
    }
    /// <summary>
    /// 超链接事件
    /// </summary>
    public HrefClickEvent onHrefClick = new HrefClickEvent();

    private LineInfo m_HrefLineInfo = null;

    /// <summary>
    /// 线偏移位置
    /// </summary>
    public float m_HrefLineOffset = 1f;
    /// <summary>
    /// 线宽度
    /// </summary>
    public float m_HrefLineHeight = 4f;
    /// <summary>
    /// 单线长度
    /// </summary>
    public float m_HrefLineLength = 10f;
    /// <summary>
    /// 虚线比例
    /// </summary> 
    [Range(0.1f, 1.2f)]
    public float m_HrefLineRario = 1f;
    #endregion

    /// <summary>
    /// 文本宽度
    /// </summary>
    public override float preferredWidth
    {
   
        get
        {
   
            var settings = GetGenerationSettings(Vector2.zero);
            float width = cachedTextGeneratorForLayout.GetPreferredWidth(m_OutputText, settings) / pixelsPerUnit;
            ContentSizeFitter fitter = GetComponent<ContentSizeFitter>();
            bool horizontalFit = fitter != null && fitter.horizontalFit == ContentSizeFitter.FitMode.PreferredSize;
            return horizontalFit ? width : width < rectTransform.sizeDelta.x || horizontalOverflow == HorizontalWrapMode.Overflow ? width : rectTransform.sizeDelta.x;
        }
    }
    /// <summary>
    /// 文本高度
    /// </summary>
    public override float preferredHeight
    {
   
        get
        {
   
            var settings = GetGenerationSettings(new Vector2(rectTransform.rect.size.x, 0.0f));
            float height = cachedTextGeneratorForLayout.GetPreferredHeight(m_OutputText, settings) / pixelsPerUnit;
            ContentSizeFitter fitter = GetComponent<ContentSizeFitter>();
            bool verticalFit = fitter != null && fitter.verticalFit == ContentSizeFitter.FitMode.PreferredSize;
            return verticalFit ? height : height < rectTransform.sizeDelta.y || verticalOverflow == VerticalWrapMode.Overflow ? height : rectTransform.sizeDelta.y;
        }
    }

    /// <summary>
    /// 字符宽度
    /// </summary>
    public float CharWidth {
    get; private set; }
    /// <summary>
    /// 字符高度
    /// </summary>
    public float CharHeight {
    get; private set; }

    /// <summary>
    /// 线长度
    /// </summary>
    private float currentLineLength = 0;

    public override string text
    {
   
        get
        {
   
            return base.text;
        }
        set
        {
   
            if (string.IsNullOrEmpty(value))
            {
   
                if (string.IsNullOrEmpty(m_Text))
                    return;
                m_Text = string.Empty;
#if !UNITY_EDITOR
                    m_OutputText = GetOutputText();
#endif
                SetVerticesDirty();
            }
            else if (m_Text != value)
            {
   
                base.text = value;
#if !UNITY_EDITOR
                    m_OutputText = GetOutputText();
#endif
                SetVerticesDirty();
                SetLayoutDirty();
            }
        }
    }

    #region 内部方法
    protected override void Awake()
    {
   
        InitInfo();

#if !UNITY_EDITOR
        m_OutputText = GetOutputText();
#endif
        Invoke("SetVerticesDirty", 0.2f);
        base.Awake();
    }

    protected override void OnEnable()
    {
   
        supportRichText = true;
        base.OnEnable();
    }

#if UNITY_EDITOR
    protected override void OnValidate()
    {
   
        InitInfo();
        SetVerticesDirty();
        LayoutRebuilder.ForceRebuildLayoutImmediate(rectTransform);
    }
#endif

    public override void SetVerticesDirty()
    {
   
#if UNITY_EDITOR
        m_OutputText = GetOutputText();
#endif
        base.SetVerticesDirty();
    }

    protected override void OnPopulateMesh(VertexHelper toFill)
    {
   
        if (font == null)
            return;

        // We don't care if we the font Texture changes while we are doing our Update.
        // The end result of cachedTextGenerator will be valid for this instance.
        // Otherwise we can get issues like Case 619238.
        m_DisableFontTextureRebuiltCallback = true;

        Vector2 extents = rectTransform.rect.size;
        var settings = GetGenerationSettings(extents);
        cachedTextGenerator.Populate(m_OutputText, settings);

        // Apply the offset to the vertices
        IList<UIVertex> verts = cachedTextGenerator.verts;
        float unitsPerPixel = 1 / pixelsPerUnit;
        //Last 4 verts are always a new line... (\n) 空格不进行顶点计算
        //int vertCount = verts.Count - 4;
        int vertCount 
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值