精华内容
下载资源
问答
  • 本资源为unity中uguiText文本插入超链接(即 网址,图片等),简单好用,只需要将manager类放到父物体身上,将initText放到Text身上,即可
  • Unity超链接可点击文本组件
  • Emoji和用于Unity UGUI的超链接文本,继承自UGUI中的文本组件,实现超链接和图文混排, 参考了 相较于GText修改了: 新增点击超链接范围外的一部分 优化下划线表现 新增了超链接颜色渐变 删除了单独的下划线 删除...
  • 图中4个DC:Unity本身1个,文本整体只有1个,0x02动态加载图片1个,0x03加载的动画1个 效果图: 输入内容: New GText 测试[AA]ceshi 测试[AB|36#dianji]ceshi自定义大小且可点击表情 测试[a|40#dianji]ceshi自定义...
  • unity 超链接文本

    2021-10-21 16:27:07
    测试: Unity 2018.4 废话不多说,直接上代码: using System; using System.Collections; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; using UnityEngine; ...

    测试: Unity 2018.4

    废话不多说,直接上代码:

    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>
    public class HyperlinkText : Text, IPointerClickHandler
    {
        /// <summary>
        /// 超链接信息类
        /// </summary>
        private class HyperlinkInfo
        {
            public int startIndex;
    
            public int endIndex;
    
            public string name;
    
            public readonly List<Rect> boxes = new List<Rect>();
        }
    
        /// <summary>
        /// 解析完最终的文本
        /// </summary>
        private string m_OutputText;
    
        /// <summary>
        /// 超链接信息列表
        /// </summary>
        private readonly List<HyperlinkInfo> m_HrefInfos = new List<HyperlinkInfo>();
    
        /// <summary>
        /// 文本构造器
        /// </summary>
        protected static readonly StringBuilder s_TextBuilder = new StringBuilder();
    
        [Serializable]
        public class HrefClickEvent : UnityEvent<string> { }
    
        [SerializeField]
        private HrefClickEvent m_OnHrefClick = new HrefClickEvent();
    
        /// <summary>
        /// 超链接点击事件
        /// </summary>
        public HrefClickEvent onHrefClick
        {
            get { return m_OnHrefClick; }
            set { m_OnHrefClick = value; }
        }
    
    
        /// <summary>
        /// 超链接正则
        /// </summary>
        private static readonly Regex s_HrefRegex = new Regex(@"<a href=([^>\n\s]+)>(.*?)(</a>)", RegexOptions.Singleline);
    
        private HyperlinkText mHyperlinkText;
    
        protected override void Awake()
        {
            base.Awake();
            mHyperlinkText = GetComponent<HyperlinkText>();
        }
        protected override void OnEnable()
        {
            base.OnEnable();
            mHyperlinkText.onHrefClick.AddListener(OnHyperlinkTextInfo);
        }
    
        protected override void OnDisable()
        {
            base.OnDisable();
            mHyperlinkText.onHrefClick.RemoveListener(OnHyperlinkTextInfo);
        }
    
    
        public override void SetVerticesDirty()
        {
            base.SetVerticesDirty();
    #if UNITY_EDITOR
            if (UnityEditor.PrefabUtility.GetPrefabType(this) == UnityEditor.PrefabType.Prefab)
            {
                return;
            }
    #endif
            m_OutputText = GetOutputText(text);
    
        }
    
    
        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 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);
                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;
            m_HrefInfos.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
                };
    
                m_HrefInfos.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();
        }
    
        /// <summary>
        /// 点击事件检测是否点击到超链接文本
        /// </summary>
        /// <param name="eventData"></param>
        public void OnPointerClick(PointerEventData eventData)
        {
            Vector2 lp = Vector2.zero;
            
            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))
                    {
                        m_OnHrefClick.Invoke(hrefInfo.name);
                        return;
                    }
                }
            }
        }
        /// <summary>
        /// 当前点击超链接回调
        /// </summary>
        /// <param name="info">回调信息</param>
        private void OnHyperlinkTextInfo(string info)
        {
            Debug.Log("超链接信息:" + info);
            Application.OpenURL(info);
        }
    }

    展开全文
  • using System; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; using UnityEngine; using UnityEngine.Events;.../// 文本控件,支持超链接 /// </summary
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Text.RegularExpressions;
    using UnityEngine;
    using UnityEngine.Events;
    using UnityEngine.EventSystems;
    using UnityEngine.UI;
    
    /// <summary>
    /// 文本控件,支持超链接
    /// </summary>
    public class HyperlinkText : Text, IPointerClickHandler
    {
        /// <summary>
        /// 超链接信息类
        /// </summary>
        private class HyperlinkInfo
        {
            public int startIndex;
    
            public int endIndex;
    
            public string name;
    
            public readonly List<Rect> boxes = new List<Rect>();
        }
    
        /// <summary>
        /// 解析完最终的文本
        /// </summary>
        private string m_OutputText;
    
        /// <summary>
        /// 超链接信息列表
        /// </summary>
        private readonly List<HyperlinkInfo> m_HrefInfos = new List<HyperlinkInfo>();
    
        /// <summary>
        /// 文本构造器
        /// </summary>
        protected static readonly StringBuilder s_TextBuilder = new StringBuilder();
    
        [Serializable]
        public class HrefClickEvent : UnityEvent<string> { }
    
        [SerializeField]
        private HrefClickEvent m_OnHrefClick = new HrefClickEvent();
    
        /// <summary>
        /// 超链接点击事件
        /// </summary>
        public HrefClickEvent onHrefClick
        {
            get { return m_OnHrefClick; }
            set { m_OnHrefClick = value; }
        }
    
    
        /// <summary>
        /// 超链接正则
        /// </summary>
        private static readonly Regex s_HrefRegex = new Regex(@"<a href=([^>\n\s]+)>(.*?)(</a>)", RegexOptions.Singleline);
    
        private HyperlinkText mHyperlinkText;
    
        
        [SerializeField]
        public string mName1 = "《服务协议》";
        
        
        [SerializeField]
        public string mName2 = "《隐私政策》";
        public string GetHyperlinkInfo
        {
            get { return string.Format("请你务必审慎阅读、充分理解“服务协议”和“隐私政策”各条款,包括但不限于:为了向您提供AR扫描模型服务,我们需要获取您移动设备相机" +
                                       "权限。你可阅读<a href={0:link}>{1:name}</a>和<a href={2:link}>{3:name}</a>了解详细信息。" +
                                       "如你同意,请点击“同意”开始接受我们的服务。", "http://www.baidu.com", mName1, "http://www.google.com", mName2); }
        }
    
        protected override void Awake()
        {
            base.Awake();
            mHyperlinkText = GetComponent<HyperlinkText>();
        }
        protected override void OnEnable()
        {
            base.OnEnable();
            mHyperlinkText.onHrefClick.AddListener(OnHyperlinkTextInfo);
        }
    
        protected override void OnDisable()
        {
            base.OnDisable();
            mHyperlinkText.onHrefClick.RemoveListener(OnHyperlinkTextInfo);
        }
    
    
        public override void SetVerticesDirty()
        {
            base.SetVerticesDirty();
    #if UNITY_EDITOR
            if (UnityEditor.PrefabUtility.GetPrefabType(this) == UnityEditor.PrefabType.Prefab)
            {
                return;
            }
    #endif
            //  m_OutputText = GetOutputText(text);
            text = GetHyperlinkInfo;
            m_OutputText = GetOutputText(text);
    
        }
    
    
        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 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);
                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;
            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("<color='#0080FF'>");  // 超链接颜色
    
                var group = match.Groups[1];
                var hrefInfo = new HyperlinkInfo
                {
                    startIndex = s_TextBuilder.Length * 4, // 超链接里的文本起始顶点索引
                    endIndex = (s_TextBuilder.Length + match.Groups[2].Length - 1) * 4 + 3,
                    name = group.Value
                };
                m_HrefInfos.Add(hrefInfo);
    
                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();
        }
    
        /// <summary>
        /// 点击事件检测是否点击到超链接文本
        /// </summary>
        /// <param name="eventData"></param>
        public void OnPointerClick(PointerEventData eventData)
        {
            Vector2 lp = Vector2.zero;
            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))
                    {
                        m_OnHrefClick.Invoke(hrefInfo.name);
                        return;
                    }
                }
            }
        }
        /// <summary>
        /// 当前点击超链接回调
        /// </summary>
        /// <param name="info">回调信息</param>
        private void OnHyperlinkTextInfo(string info)
        {
            Debug.Log("超链接信息:" + info);
        }
    
    }
    
    
    展开全文
  • Unity添加超链接文本

    千次阅读 2019-11-04 21:29:43
    原文中正则表达式"<a href=([^>\n\s]+)>(.*?)(</a>)"的s前面只有一条\,实际应该是两条,这样才...扩展Text组件,使用时直接添加HyperlinkText 组件即可,超链接格式为<a href="text">text&l...

    原文在这里:https://www.jianshu.com/p/76c45c2f6383

    原文中正则表达式"<a href=([^>\n\s]+)>(.*?)(</a>)"的s前面只有一条\,实际应该是两条,这样才能够匹配空格。

    扩展Text组件,使用时直接添加HyperlinkText 组件即可,超链接格式为<a href="text">text</a>

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Text.RegularExpressions;
    using UnityEngine;
    using UnityEngine.Events;
    using UnityEngine.EventSystems;
    using UnityEngine.UI;
    
    /// <summary>
    /// 文本控件,支持超链接
    /// </summary>
    public class HyperlinkText : Text, IPointerClickHandler
    {
        /// <summary>
        /// 超链接信息类
        /// </summary>
        private class HyperlinkInfo
        {
            public int startIndex;
    
            public int endIndex;
    
            public string name;
    
            public readonly List<Rect> boxes = new List<Rect>();
        }
    
        /// <summary>
        /// 解析完最终的文本
        /// </summary>
        private string m_OutputText;
    
        /// <summary>
        /// 超链接信息列表
        /// </summary>
        private readonly List<HyperlinkInfo> m_HrefInfos = new List<HyperlinkInfo>();
    
        /// <summary>
        /// 文本构造器
        /// </summary>
        protected static readonly StringBuilder s_TextBuilder = new StringBuilder();
    
        [Serializable]
        public class HrefClickEvent : UnityEvent<string> { }
    
        [SerializeField]
        private HrefClickEvent m_OnHrefClick = new HrefClickEvent();
    
        /// <summary>
        /// 超链接点击事件
        /// </summary>
        public HrefClickEvent onHrefClick
        {
            get { return m_OnHrefClick; }
            set { m_OnHrefClick = value; }
        }
        /// <summary>
        /// 超链接正则
        /// </summary>
        private static readonly Regex s_HrefRegex = new Regex(@"<a href=([^>\n\\s]+)>(.*?)(</a>)", RegexOptions.Singleline);
        
        public override void SetVerticesDirty()
        {
            base.SetVerticesDirty();
    #if UNITY_EDITOR
            if (UnityEditor.PrefabUtility.GetPrefabAssetType(this) == UnityEditor.PrefabAssetType.Model)
            {
                return;
            }
    #endif
            m_OutputText = GetOutputText(text);
        }
        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 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);
                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;
            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("<color=blue>");  // 超链接颜色
    
                var group = match.Groups[1];
                var hrefInfo = new HyperlinkInfo
                {
                    startIndex = s_TextBuilder.Length * 4, // 超链接里的文本起始顶点索引
                    endIndex = (s_TextBuilder.Length + match.Groups[2].Length - 1) * 4 + 3,
                    name = group.Value
                };
                m_HrefInfos.Add(hrefInfo);
    
                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();
        }
        /// <summary>
        /// 点击事件检测是否点击到超链接文本
        /// </summary>
        /// <param name="eventData"></param>
        public void OnPointerClick(PointerEventData eventData)
        {
            Vector2 lp = Vector2.zero;
            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))
                    {
                        m_OnHrefClick.Invoke(hrefInfo.name);
                        return;
                    }
                }
            }
        }
    }

    下面是如何访问回调函数

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class Test: MonoBehaviour
    {    
        // Start is called before the first frame update
        void Start()
        {
            transform.GetComponent<HyperlinkText>().onHrefClick.AddListener(OnHrefClick);//监听文本中的超链接的点击事件
        }    
        
        /// <summary>
        /// 文本超链接的回调函数
        /// </summary>
        /// <param name="hrefName"></param>
        private void OnHrefClick(string hrefName)
        {
            Debug.Log("点击了超链接:" + hrefName);                               
        }    
    }

    这个脚本有一个问题,就是HyperlinkText计算长度时会把整个超链接的长度计算在内,而不是仅计算超链接中显示的文本,所以有些情况超链接会失效

    展开全文
  • Unity Text 超链接插件

    2015-10-09 22:56:03
    this is limited version of Text Action Pro (no anim support, no fade duration, no phase for curve, no example scene due to reaching 2MB limit, but added small documentation from TAPro) + contemporary ...
  • Unity Text 实现文本超链接 由于Unity2019.1.5f1及更高版本不再存储Text的完整vertex信息,不支持unity2019.1.5f1及更高版本,所以以前的脚本不适用新的Text。因此,重新实现文本超链接功能。

    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 = verts.Count;
            // We have no verts to process just return (case 1037923)
            if (vertCount <= 0)
            {
                toFill.Clear();
                return;
            }
    
            Vector2 roundingOffset = new Vector2(verts[0].position.x, verts[0].position.y) * unitsPerPixel;
            roundingOffset = PixelAdjustPoint(roundingOffset) - roundingOffset;
            toFill.Clear();
    
            List<Vector3> _vertsPosList = new List<Vector3>();
            if (roundingOffset != Vector2.zero)
            {
                for (int i = 0; i < vertCount; ++i)
                {
                    int tempVertsIndex = i & 3;
                    m_TempVerts[tempVertsIndex] = verts[i];
                    m_TempVerts[tempVertsIndex].position *= unitsPerPixel;
                    m_TempVerts[tempVertsIndex].position.x += roundingOffset.x;
                    m_TempVerts[tempVertsIndex].position.y += roundingOffset.y;
                    if (tempVertsIndex == 3)
                        toFill.AddUIVertexQuad(m_TempVerts);
                    _vertsPosList.Add(m_TempVerts[tempVertsIndex].position);
                }
            }
            else
            {
                for (int i = 0; i < vertCount; ++i)
                {
                    int tempVertsIndex = i & 3;
                    m_TempVerts[tempVertsIndex] = verts[i];
                    m_TempVerts[tempVertsIndex].position *= unitsPerPixel;
                    if (tempVertsIndex == 3)
                        toFill.AddUIVertexQuad(m_TempVerts);
                    _vertsPosList.Add(m_TempVerts[tempVertsIndex].position);
                }
            }
    
            CalculateBoundBoxInfo(_vertsPosList, m_HrefInfos);
            DrawUnderLine(toFill, settings, m_HrefInfos, m_HrefLineInfo);
    
            m_DisableFontTextureRebuiltCallback = false;
        }
    
        /// <summary>
        /// 初始化数据信息
        /// </summary>
        private void InitInfo()
        {
            m_HrefLineInfo = new LineInfo()
            {
                m_LineOffset = m_HrefLineOffset,
                m_LineHeight = m_HrefLineHeight,
                m_SingleLineLength = m_HrefLineLength,
                m_BrokenLineRario = m_HrefLineRario,
                m_SingleLineRatio = 1.2f,
                m_LineRatio = 0.1f,
                m_OffsetRatio = 0f,
            };
        }
    
        protected string GetOutputText()
        {
    
            #region 初始化数据
    
            m_HrefInfos.Clear();
            isHaveHref = false;
    
            m_TextBuilder.Length = 0;
            var unMatchIndex = 0;
    
            #endregion
    
            if (string.IsNullOrEmpty(text))
                return string.Empty;
    
            string inputText = text;
    
            Vector2 extents = rectTransform.rect.size;
            TextGenerationSettings settings = GetGenerationSettings(extents);
    
            CharWidth = cachedTextGeneratorForLayout.GetPreferredWidth(inputText, settings) / this.pixelsPerUnit;
            if (cachedTextGeneratorForLayout.GetCharactersArray().Length > 0)
                CharWidth = cachedTextGeneratorForLayout.GetCharactersArray()[0].charWidth;
    
            CharHeight = cachedTextGeneratorForLayout.GetPreferredHeight(inputText, settings) / this.pixelsPerUnit;
            if (cachedTextGeneratorForLayout.GetLinesArray().Length > 0)
                CharHeight = cachedTextGeneratorForLayout.GetLinesArray()[0].height;
    
            int startIndex = 0;
            int tempIndex = 0;
            int endIndex = 0;
            foreach (Match match in m_Regex.Matches(inputText))
            {
    
                #region 解析数据
    
                var _type = match.Groups[1].Value;
                MatchType _matchType = MatchType.none;
                if (Enum.IsDefined(typeof(MatchType), _type))
                    _matchType = (MatchType)Enum.Parse(typeof(MatchType), _type);
                else
                    _matchType = MatchType.none;
    
                var _id = match.Groups[2].Value;
    
                string _name = string.Empty;
                if (match.Groups[4].Success)
                    _name = match.Groups[4].Value;
                else
                    _name = string.Empty;
    
                float width = 0f;
                float height = 0f;
                if (match.Groups[5].Success)
                {
                    string _size = match.Groups[5].Value;
                    string[] _sizes = _size.Split('|');
                    width = _sizes.Length > 1 ? float.Parse(_sizes[1]) : CharHeight;
                    height = _sizes.Length == 3 ? float.Parse(_sizes[2]) : width;
                }
                else
                {
                    width = CharHeight;
                    height = CharHeight;
                }
    
                string _content = string.Empty;
                if (match.Groups[4].Success)
                    _content = match.Groups[8].Value;
                else
                    _content = string.Empty;
    
                string _color1 = string.Empty;
                string _color2 = string.Empty;
                if (match.Groups[10].Success)
                {
                    string _color = match.Groups[10].Value;
                    string[] _colors = _color.Split('|');
                    _color1 = _colors.Length > 1 ? _colors[1] : string.Empty;
                    _color2 = _colors.Length == 3 ? _colors[2] : string.Empty;
                }
                else
                {
                    _color1 = string.Empty;
                    _color2 = string.Empty;
                }
    
                #endregion
    
                isHaveHref = true;
                Color _contentColor = GetColor(_color1, Color.blue);
                Color _lineColor = GetColor(_color1, Color.blue);
                string color1 = GetColor(_contentColor);
    
                string unMatchContent = inputText.Substring(unMatchIndex, match.Index - unMatchIndex);
                m_TextBuilder.Append(unMatchContent);
                int space = GetSpaceCount(unMatchContent);
                startIndex = (m_TextBuilder.Length - space) * 4 - tempIndex + endIndex;
                if (_id.Contains("S"))
                {
                    m_TextBuilder.Append("<color=#");
                    m_TextBuilder.Append(color1);
                    m_TextBuilder.Append(">[</color>");
                }
                else if (_id.Contains("s"))
                {
                    m_TextBuilder.Append("<color=#");
                    m_TextBuilder.Append(color1);
                    m_TextBuilder.Append(">(</color>");
                }
    
                m_TextBuilder.Append("<color=#");
                m_TextBuilder.Append(color1);
                m_TextBuilder.Append(">");
                tempIndex = m_TextBuilder.Length * 4;
                m_TextBuilder.Append(_content);
                 space = GetSpaceCount(_content);
                endIndex = (m_TextBuilder.Length - space) * 4 - tempIndex + startIndex;
                m_TextBuilder.Append("</color>");
    
                if (_id.Contains("S"))
                {
                    m_TextBuilder.Append("<color=#");
                    m_TextBuilder.Append(color1);
                    m_TextBuilder.Append(">]</color>");
                }
                else if (_id.Contains("s"))
                {
                    m_TextBuilder.Append("<color=#");
                    m_TextBuilder.Append(color1);
                    m_TextBuilder.Append(">)</color>");
                }
    
                tempIndex = m_TextBuilder.Length * 4;
    
                var href = new HrefInfo()
                {
                    id = _id,
                    startIndex = startIndex,
                    endIndex = endIndex,
                    name = _name,
                    color = _lineColor,
                    url = _content,
                };
                m_HrefInfos.Add(href);
    
                unMatchIndex = match.Index + match.Length;
            }
    
            m_TextBuilder.Append(inputText.Substring(unMatchIndex, inputText.Length - unMatchIndex));
            return m_TextBuilder.ToString();
        }
    
        /// <summary>
        /// 计算包围框数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="vertsPosList"></param>
        /// <param name="boxInfo"></param>
        private void CalculateBoundBoxInfo<T>(List<Vector3> vertsPosList, List<T> boxInfo)
          where T : BoxInfo
        {
            foreach (var boundInfo in boxInfo)
            {
                boundInfo.boxes.Clear();
                Debug.LogError(boundInfo.startIndex+"  "+ vertsPosList.Count);
                if (boundInfo.startIndex >= vertsPosList.Count)
                    continue;
    
                // 将文本顶点索引坐标加入到包围框  
                var pos = vertsPosList[boundInfo.startIndex];
                var bounds = new Bounds(pos, Vector3.zero);
    
                for (int i = boundInfo.startIndex, m = boundInfo.endIndex; i < m; i++)
                {
                    if (i >= vertsPosList.Count)
                        break;
                    pos = vertsPosList[i];
                    if ((i - 1) >= 0 && pos.x < vertsPosList[i - 1].x && pos.y < vertsPosList[i - 1].y)
                    {
                        // 换行重新添加包围框
                        boundInfo.boxes.Add(new Rect(bounds.min, bounds.size));
                        bounds = new Bounds(pos, Vector3.zero);
                    }
                    else
                    {
                        bounds.Encapsulate(pos); // 扩展包围框
                    }
                }
                //添加包围框
                boundInfo.boxes.Add(new Rect(bounds.min, bounds.size));
            }
        }
    
        /// <summary>
        /// 画线- 多条线 实线-虚线
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="toFill"></param>
        /// <param name="settings"></param>
        /// <param name="boxInfo"></param>
        /// <param name="info"></param>
        private void DrawUnderLine<T>(VertexHelper toFill, TextGenerationSettings settings, List<T> boxInfo, LineInfo info)
          where T : BoxInfo
        {
            if (boxInfo.Count <= 0)
                return;
    
            #region 添加下划线
            TextGenerator _lineTextGenerator = new TextGenerator();
            _lineTextGenerator.Populate("_", settings);
            IList<UIVertex> _verts = _lineTextGenerator.verts;
    
            #region 初始化线数据
    
            float _lineOffset = info.m_LineOffset;
            float _lineHeight = info.m_LineHeight;
            float _singleLineLength = info.m_SingleLineLength;
            float _brokenLineRario = info.m_BrokenLineRario;
            float _singleLineRatio = info.m_SingleLineRatio;
            float _lineRatio = info.m_LineRatio;
            float _offsetRatio = info.m_OffsetRatio;
    
            #endregion
    
            float singleRatio = _singleLineRatio;
            float offsetRatio = _offsetRatio;
            Vector3[] _ulPos = new Vector3[4];
    
            foreach (var item in boxInfo)
            {
                for (int i = 0; i < item.boxes.Count; i++)
                {
                    currentLineLength = 0;
                    float singleLength = _singleLineLength;
    
                    int count = (int)Math.Ceiling(item.boxes[i].width / _singleLineLength);
                    if (count == 1)
                        singleRatio = _singleLineRatio;
                    else
                        singleRatio = _singleLineRatio + _lineRatio;
    
                    for (int m = 0; m < count; m++)
                    {
                        if (m == 0)
                            offsetRatio = _offsetRatio;
                        else
                            offsetRatio = (singleRatio - 1) / 2f;
    
                        if (m == count - 1)
                        {
                            if (item.boxes[i].width - m * _singleLineLength < _singleLineLength)
                            {
                                singleLength = item.boxes[i].width - m * _singleLineLength - 1.5f * singleRatio;
                            }
                        }
    
                        //Debug.Log("count   " + count + "  偏移率   " + offsetRatio + "  singleLength  " + singleLength + "singleLineLength   " + singleLineLength + " singleRatio  " + singleRatio+ "  currentLineLength " + currentLineLength);
    
                        //计算下划线的位置
                        Vector3 _pos = item.boxes[i].position + new Vector2(currentLineLength, 0.0f) + new Vector2(0, _lineOffset);
                        _ulPos[0] = _pos + new Vector3(-1 * singleLength * offsetRatio, 0.0f);
                        _ulPos[1] = _ulPos[0] + new Vector3(singleLength * singleRatio, 0.0f) * _brokenLineRario;
                        _ulPos[2] = _ulPos[0] + new Vector3(singleLength * singleRatio, 0.0f) * _brokenLineRario + new Vector3(0.0f, -_lineHeight);
                        _ulPos[3] = _ulPos[0] + new Vector3(0.0f, -_lineHeight);
    
                        currentLineLength += singleLength;
    
                        //绘制下划线
                        for (int j = 0; j < 4; j++)
                        {
                            m_TempVerts[j] = _verts[j];
                            m_TempVerts[j].color = item.color;
                            m_TempVerts[j].position = _ulPos[j];
                            if (j == 3)
                                toFill.AddUIVertexQuad(m_TempVerts);
                        }
    
                    }
    
                }
            }
    
            _lineTextGenerator = null;
            #endregion
        }
    
        #endregion
    
        #region 点击事件相关
    
        void IPointerClickHandler.OnPointerClick(PointerEventData eventData)
        {
            if (!isHaveHref)
                return;
            Vector2 localPoint;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(
                rectTransform, eventData.position, eventData.pressEventCamera, out localPoint);
    
            foreach (var hrefInfo in m_HrefInfos)
            {
                var boxes = hrefInfo.boxes;
                for (var i = 0; i < boxes.Count; ++i)
                {
                    if (boxes[i].Contains(localPoint))
                    {
                        onHrefClick.Invoke(hrefInfo.id, hrefInfo.name, hrefInfo.url);
                        return;
                    }
                }
            }
        }
    
        #endregion
    
        #region 辅助相关
    
        /// <summary>
        /// 获取颜色
        /// </summary>
        /// <param name="color">16进制字符/颜色</param>
        /// <param name="oldColor"></param>
        /// <returns></returns>
        private Color GetColor(string color, Color oldColor)
        {
            Color newColor = oldColor;
            if (!string.IsNullOrEmpty(color))
            {
                bool IsDefined = ColorUtility.TryParseHtmlString(color, out newColor);
                if(IsDefined == false)
                {
                    IsDefined = ColorUtility.TryParseHtmlString("#" + color, out newColor);
                }
                if (!IsDefined)
                    newColor = base.color;
            }
            return newColor;
        }
        /// <summary>
        /// 获取16进制颜色
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
        private string GetColor(Color color)
        {
            return ColorUtility.ToHtmlStringRGB(color);
        }
    
        /// <summary>
        /// 获取文本空格数据
        /// </summary>
        /// <param name="content"></param>
        /// <returns></returns>
        private int GetSpaceCount(string content)
        {
            int count = 0;
            if (content.Contains(" "))
            {
                string[] spaces = content.Split(' ');
                count = spaces.Length - 1;
            }
            return count;
        }
    
        #endregion
    
        #region 信息类
        /// <summary>
        /// 匹配类型
        /// </summary>
        private enum MatchType
        {
            none,
            /// <summary>
            /// 填空
            /// </summary>
            gap,
            /// <summary>
            /// 超链接
            /// </summary>
            href,
            /// <summary>
            /// 图标
            /// </summary>
            icon,
            /// <summary>
            /// 线
            /// </summary>
            line,
        }
    
        /// <summary>
        /// 线类型
        /// </summary>
        protected enum LineType
        {
            /// <summary>
            /// 直线
            /// </summary>
            straight,
            /// <summary>
            /// 波浪线
            /// </summary>
            wavy,
        }
    
        /// <summary>
        /// 线信息类
        /// </summary>
        [Serializable]
        protected class LineInfo
        {
            /// <summary>
            /// 线垂直偏移位置
            /// </summary>
            public float m_LineOffset = 0f;
            /// <summary>
            /// 线宽度
            /// </summary>
            public float m_LineHeight = 4;
            /// <summary>
            /// 单线长度
            /// </summary>
            public float m_SingleLineLength = 20;
            /// <summary>
            /// 虚线比例
            /// </summary>
            [Range(0.1f, 1.2f)]
            public float m_BrokenLineRario = 1f;
            /// <summary>
            /// 单线比例
            /// </summary>
            public float m_SingleLineRatio = 1.2f;
            /// <summary>
            /// 单线修正比例
            /// </summary>
            public float m_LineRatio = 0.1f;
            /// <summary>
            /// 水平偏移比例
            /// </summary>
            public float m_OffsetRatio = 0.1f;
    
            /// <summary>
            /// 线类型
            /// </summary>
            protected LineType m_LineType = LineType.straight;
        }
    
        /// <summary>
        /// 超链接信息类
        /// </summary>
        private class HrefInfo : BoxInfo
        {
            public string url;
        }
    
        /// <summary>
        /// 边界信息类
        /// </summary>
        private class BoxInfo
        {
            public string id;
    
            public int startIndex;
    
            public int endIndex;
    
            public string name;
    
            public Color color;
    
            public readonly List<Rect> boxes = new List<Rect>();
        }
        #endregion
    
    }
    

    Editor扩展:

    using UnityEditor;
    using UnityEditor.UI;
    using UnityEngine;
    
    [CustomEditor(typeof(UIText), true)]
    [CanEditMultipleObjects]
    public class UITextEditor : GraphicEditor
    {
    
        SerializedProperty m_Text;
        SerializedProperty m_FontData;
    
        SerializedProperty m_TextIndent;
        SerializedProperty m_IndentCharCount;
    
        SerializedProperty m_IsHaveGap;
        SerializedProperty m_IsRichTextColor;
        SerializedProperty m_GapColor;
        SerializedProperty m_LineColor;
        SerializedProperty m_LineOffset;
        SerializedProperty m_LineHeight;
        SerializedProperty m_GapLineLength;
        SerializedProperty m_GapLineRario;
        SerializedProperty m_GapPrefabPath;
    
        SerializedProperty m_IsHaveHref;
        SerializedProperty m_HrefLineOffset;
        SerializedProperty m_HrefLineHeight;
        SerializedProperty m_onHrefClick;
        SerializedProperty m_HrefLineLength;
        SerializedProperty m_HrefLineRario;
    
        SerializedProperty m_IsHaveLine;
        SerializedProperty m_LowLineOffset;
        SerializedProperty m_MiddleLineOffset;
        SerializedProperty m_HighLineOffset;
        SerializedProperty m_LineHeightOffset;
        SerializedProperty m_LineLength;
        SerializedProperty m_LineRario;
    
        private static bool gapToggle;
        private static bool gapFaldout = true;
    
        private static bool hrefToggle;
        private static bool hrefFaldout = true;
    
        private static bool lineToggle;
        private static bool lineFaldout = true;
    
        protected override void OnEnable()
        {
            base.OnEnable();
    
            m_Text = serializedObject.FindProperty("m_Text");
            m_FontData = serializedObject.FindProperty("m_FontData");
    
            m_TextIndent = serializedObject.FindProperty("textIndent");
            m_IndentCharCount = serializedObject.FindProperty("indentCharCount");
    
            m_IsHaveGap = serializedObject.FindProperty("isHaveGap");
            m_IsRichTextColor = serializedObject.FindProperty("m_IsRichTextColor");
            m_GapColor = serializedObject.FindProperty("m_GapColor");
            m_LineColor = serializedObject.FindProperty("m_LineColor");
            m_LineOffset = serializedObject.FindProperty("m_LineOffset");
            m_LineHeight = serializedObject.FindProperty("m_LineHeight");
            m_GapLineLength = serializedObject.FindProperty("m_SingleLineLength");
            m_GapLineRario = serializedObject.FindProperty("m_BrokenLineRario");
            m_GapPrefabPath = serializedObject.FindProperty("InputFieldPrefabPath");
    
            m_IsHaveHref = serializedObject.FindProperty("isHaveHref");
            m_HrefLineOffset = serializedObject.FindProperty("m_HrefLineOffset");
            m_HrefLineHeight = serializedObject.FindProperty("m_HrefLineHeight");
            m_onHrefClick = serializedObject.FindProperty("onHrefClick");
            m_HrefLineLength = serializedObject.FindProperty("m_HrefLineLength");
            m_HrefLineRario = serializedObject.FindProperty("m_HrefLineRario");
    
            m_IsHaveLine = serializedObject.FindProperty("isHaveLine");
            m_LowLineOffset = serializedObject.FindProperty("m_LowLineOffset");
            m_MiddleLineOffset = serializedObject.FindProperty("m_MiddleLineOffset");
            m_HighLineOffset = serializedObject.FindProperty("m_HighLineOffset");
            m_LineHeightOffset = serializedObject.FindProperty("m_LineHeightOffset");
            m_LineLength = serializedObject.FindProperty("m_LineLength");
            m_LineRario = serializedObject.FindProperty("m_LineRario");
        }
    
        public override void OnInspectorGUI()
        {
            serializedObject.Update();
    
            EditorGUILayout.PropertyField(m_Text);
            EditorGUILayout.PropertyField(m_FontData);
    
            EditorGUILayout.PropertyField(m_TextIndent, new GUIContent("    TextIndent"));
            if (m_TextIndent.boolValue)
                EditorGUILayout.PropertyField(m_IndentCharCount, new GUIContent("    IndentCharCount"));
    
            AppearanceControlsGUI();
    
            if (m_IsHaveGap.boolValue)
            {
                gapToggle = EditorGUILayout.Toggle("GapInfo", gapToggle);
                if (gapToggle)
                {
                    gapFaldout = EditorGUILayout.Foldout(gapFaldout, "GapInfo");
                    if (gapFaldout)
                    {
                        m_IsRichTextColor.boolValue = EditorGUILayout.Toggle("    IsRichTextColor", m_IsRichTextColor.boolValue);
                        EditorGUILayout.PropertyField(m_GapColor, new GUIContent("    GapColor"));
                        EditorGUILayout.PropertyField(m_LineColor, new GUIContent("    LineColor"));
                        EditorGUILayout.PropertyField(m_LineOffset, new GUIContent("    LineOffset"));
                        EditorGUILayout.PropertyField(m_LineHeight, new GUIContent("    LineHeight"));
                        EditorGUILayout.PropertyField(m_GapLineLength, new GUIContent("    LineLength"));
                        EditorGUILayout.PropertyField(m_GapLineRario, new GUIContent("    LineRario"));
                        EditorGUILayout.PropertyField(m_GapPrefabPath, new GUIContent("    GapPrefabPath"));
                        EditorGUILayout.Space();
                    }
                }
            }
    
            if (m_IsHaveHref.boolValue)
            {
                hrefToggle = EditorGUILayout.Toggle("HrefInfo", hrefToggle);
                if (hrefToggle)
                {
                    hrefFaldout = EditorGUILayout.Foldout(hrefFaldout, "HrefInfo");
                    if (hrefFaldout)
                    {
                        EditorGUILayout.PropertyField(m_HrefLineOffset, new GUIContent("    LineOffset"));
                        EditorGUILayout.PropertyField(m_HrefLineHeight, new GUIContent("    LineHeight"));
                        EditorGUILayout.PropertyField(m_HrefLineLength, new GUIContent("    LineLength"));
                        EditorGUILayout.PropertyField(m_HrefLineRario, new GUIContent("    LineRario"));
                        EditorGUILayout.PropertyField(m_onHrefClick);
                    }
                }
            }
    
            if (m_IsHaveLine.boolValue)
            {
                lineToggle = EditorGUILayout.Toggle("LineInfo", lineToggle);
                if (lineToggle)
                {
                    lineFaldout = EditorGUILayout.Foldout(lineFaldout, "LineInfo");
                    if (lineFaldout)
                    {
                        EditorGUILayout.PropertyField(m_LowLineOffset, new GUIContent("    LowLineOffset"));
                        EditorGUILayout.PropertyField(m_MiddleLineOffset, new GUIContent("    MiddleLineOffset"));
                        EditorGUILayout.PropertyField(m_HighLineOffset, new GUIContent("    HighLineOffset"));
                        EditorGUILayout.PropertyField(m_LineHeightOffset, new GUIContent("    LineHeightOffset"));
                        EditorGUILayout.PropertyField(m_LineLength, new GUIContent("    LineLength"));
                        EditorGUILayout.PropertyField(m_LineRario, new GUIContent("    LineRario"));
                    }
                }
            }
    
            EditorGUILayout.PropertyField(m_RaycastTarget);
    
            serializedObject.ApplyModifiedProperties();
        }
    
    }
    

    示例:

    显示效果

    Text文本内容:
        1      2       <href=1#11##1234        5/>2343         11<href=1#11##1    2345/> 132         111111111 11111 4 <href=1#11##1213413 45#color|FF0000/> 123 412 3
    

    部分使用内容

    展开全文
  • Unity Text 插入超链接

    万次阅读 多人点赞 2015-10-12 18:52:19
    Unity 新 UI 系统中的 Text 组件支持富文本标签,标签包括 b(黑体)、i(斜体)、size(大小)、color(颜色),并不支持超链接以及超链接点击。之前一篇实现了简单的插入图片方法,见《Unity Text 插入图片》。...
  • Unity UGUI兼容超链接文本

    千次阅读 2021-12-23 10:58:05
    超链接格式:<a href=www.baidu.com>百度</a> using System; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; using UnityEngine; using UnityEngine....
  • Unity Text加入超链接

    千次阅读 2015-12-20 18:07:15
    Unity 新 UI 系统中的 Text 组件支持富文本标签,标签包括 b(黑体)、i(斜体)、size(大小)、color(颜色),并不支持超链接以及超链接点击。之前一篇实现了简单的插入图片方法,见《Unity Text 插入图片》...
  • /// /// 文本控件,支持超链接 /// public class HyperlinkText : Text, IPointerClickHandler { //超级连接文本样板0:[本篇博客] //超级连接文本样板1: private string lang0 = "[隐私政策]"; /// /// 超链接信息...
  • Unity UGUI Text实现超链接点击

    千次阅读 2020-02-18 16:19:48
    一开始我在网上找这种实现方法,但是发现的确有很多,但是都有问题乱七八糟的,我就修改然后整理成可以用的了。OK,Fine.就这样。 首先新建一个Text,然后删掉Text组件,并且把下面的代码拷贝然后挂载到新建的Text上。...
  • 在网上原有的继承于UGUI的Text基础上根据正则表达式找出表情标记文本替换为表情图片并实现序列帧动画的基础上扩展了下划线和超链接功能,跟UGUI的下划线和超链接功能一样
  • Unity UGUI实现图文混排组件——EmojiText(支持图标,动态表情,按钮,超链接
  • Unity TextMeshProUGUI点击超链接跳转

    千次阅读 2020-08-25 16:48:56
    using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.EventSystems; ...public class TestClickRichText : MonoBehaviour, IPointerClickHandler ...
  • unity3dText实现超链接

    千次阅读 2017-06-30 15:43:00
    startIndex = s_TextBuilder.Length * 4, // 超链接里的文本起始顶点索引 endIndex = (s_TextBuilder.Length + match.Groups[2].Length - 1) * 4 + 3, name = group.Value }; m_HrefInfos.Add(hrefInfo); s_...
  • TextMeshPro文本超链接

    千次阅读 2020-12-05 16:36:08
    超链接书写标记 <link="ID">my link</link> Canvas渲染模式选择: 挂载脚本: using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine....
  • Unity 图文混排超链接图片均可点击

    千次阅读 2018-03-12 16:04:50
    文本控件,支持超链接、图片 /// [AddComponentMenu( "UI/LinkImageText" , 10 )] public class LinkImageText : RichText, IPointerClickHandler { /// /// 解析完最终的文本 /// ...
  • Unity UGUI图文混排(六) -- 超链接

    千次阅读 2016-10-25 11:14:44
    图文混排更新到超链接这儿,好像也差不多了,不过就在最后一点,博主也表现得相当不专业,直接整合了山中双木林同学提供的超链接的解决方案,博主甚至没来得及细看就直接复制了,但感觉还是挺好用的。 博主已经将...
  • Unity的富文本语法

    2021-11-19 22:26:48
    UI中TEXT的富文本语法(要勾选rich text) <b>粗体</b> <i>斜体</i> <size=1>字号</size> <color=red>颜色</color>
  • 文本超链接(附下划线),文本内插入图片
  • 修改文本的透明度,十六进制 <indent=15%>缩进,可以用像素、百分比、字体单位,缩进会一直存在,直到遇到结束标签 <line-indent=15%> 单行缩进 加粗 斜体 加下划线 加删除线 上移 下移 <mark=...
  • Unity里UGUI中Text组件可以使用富文本。其实也可以通过Debug.Log 中使用符富文本 来区别输出内容。官方说明文档 https://docs.unity3d.com/Manual/StyledText.html 比如下面这样。 我们可以通过下面对string 的扩展...
  • Unity3D NGUI制作文字超链接

    千次阅读 2013-07-01 20:06:47
    效果 制作一个没有背景和label的Button,在button下添加两个label,一个显示文字一个显示“_”(下划线),根据文字长度计算下划线长度 看起来效果不是那么好。
  • 文本和图像组件在官方文档中被称为Visual Components可视组件,是其他一些被称为Interaction Components交互组件基础。交互组件的外观都是由文本和图像组件构成的,Interaction Components交互组件的外观调整都是...
  • [url=https://www.baidu.com/privacy_policy.html][u][ffff00]隐私政策和用户协议[-][/u][/url]

空空如也

空空如也

1 2 3 4 5 ... 12
收藏数 226
精华内容 90
关键字:

unity文本超链接