Unity3D UGUI Text 文本字间距( 支持RichText、Warp换行与PreferedWidth)

Unity3D UGUI 字间隔

  • 效果
  • 思路
  • 脚本

项目有遇到Text字间隔的问题 可惜ugui原生不支持 参考网络上的脚本做了一版

效果

Unity3D UGUI Text 文本字间距( 支持RichText、Warp换行与PreferedWidth)_第1张图片Unity3D UGUI Text 文本字间距( 支持RichText、Warp换行与PreferedWidth)_第2张图片

思路

1.依赖内置的cachedTextGenerator,通过其生成的每行数据取得对应的Vertex初始点并在生成顶点时对每个有效字体的六个顶点进行偏移操作.
2.对于富文本组件需要在生成Vertex节点时使用正则表达式提取忽略的Vertex初始点.
3.ContentSizeFitter组件需要获取PreferedWidth,TextGenerator.生成数据的最大行数算出额外Width与基础Width叠加

脚本

可以直接放到项目里使用

1.由于覆写Text 使用时请添加UIT_TextExtend而不是Text

using UnityEngine.UI;
using UnityEngine;
using System.Collections.Generic;
using System.Text.RegularExpressions;

[AddComponentMenu("UI/Text_Extend",0)]
public class UIT_TextExtend : Text
{
    public int m_characterSpacing;
	//正则表达式参数
    private const string m_RichTextRegexPatterns = @"|||||||||||||";
   
   //ContentSizeFitter的PreferdWidth获取
    public override float preferredWidth
    {
        get
        {
        	//获取初始宽度
            float preferredWidth= cachedTextGenerator.GetPreferredWidth(text, GetGenerationSettings( Vector2.zero));
            
            //根据生成的有效初始顶点数据获得最大行数的初始顶点数量
            List<List<int>> linesVertexStartIndexes = GetLinesVertexStartIndexes();
            int maxLineCount = 0;
            for (int i=0;i<linesVertexStartIndexes.Count;i++)
                maxLineCount = Mathf.Max(maxLineCount, linesVertexStartIndexes[i].Count);
                
            return preferredWidth + m_characterSpacing * (maxLineCount - 1);
        }
    } 
	
	//定点生成覆写
    //当前使用的字数像素偏移方案为(字数*偏移值) 请根据需求自行配置
    protected override void OnPopulateMesh(VertexHelper toFill)
    {
        base.OnPopulateMesh(toFill);
        if (m_characterSpacing == 0)
            return;
        List<UIVertex> vertexes = new List<UIVertex>();
        toFill.GetUIVertexStream(vertexes);

        List<List<int>> linesVertexStartIndexes = GetLinesVertexStartIndexes();
        float alignmentFactor = GetAlignmentFactor();

        for (int i = 0; i < linesVertexStartIndexes.Count; i++)
        {
        	//行偏移(左中右) 
            float lineOffset = (linesVertexStartIndexes[i].Count - 1) * m_characterSpacing * alignmentFactor;
            for (int j = 0; j < linesVertexStartIndexes[i].Count; j++)
            {
                int vertexStartIndex = linesVertexStartIndexes[i][j];
                Vector3 offset = Vector3.right * ((m_characterSpacing * j) - lineOffset);
                //对每个有效字体的六个顶点偏移
                AddVertexOffset(vertexes, vertexStartIndex + 0, offset);
                AddVertexOffset(vertexes, vertexStartIndex + 1, offset);
                AddVertexOffset(vertexes, vertexStartIndex + 2, offset);
                AddVertexOffset(vertexes, vertexStartIndex + 3, offset);
                AddVertexOffset(vertexes, vertexStartIndex + 4, offset);
                AddVertexOffset(vertexes, vertexStartIndex + 5, offset);
            }
        }

        toFill.Clear();
        toFill.AddUIVertexTriangleStream(vertexes);
    }
	//对顶点进行偏移
    void AddVertexOffset(List<UIVertex> vertexes,int index,Vector3 offset)
    {
        UIVertex vertex = vertexes[index];
        vertex.position += offset;
        vertexes[index] = vertex;
    }
	//获取有效的初始顶点
    List<List<int>> GetLinesVertexStartIndexes()
    {
        List<List<int>> linesVertexIndexes = new List<List<int>>();
        IList<UILineInfo> lineInfos = cachedTextGenerator.lines;
        for(int i=0;i<lineInfos.Count;i++)
        {
            List<int> lineVertexStartIndex = new List<int>();
            int lineStart = lineInfos[i].startCharIdx;
            int lineLength = (i < lineInfos.Count - 1) ? lineInfos[i + 1].startCharIdx - lineInfos[i].startCharIdx:text.Length - lineInfos[i].startCharIdx;
            
			//Rich Text根据正则表达式获取需要忽略的初始顶点
            List<int> ignoreIndexes = new List<int>();
            if (supportRichText)
            {
                string line = text.Substring(lineStart, lineLength);
                foreach (Match matchTag in Regex.Matches(line, m_RichTextRegexPatterns))
                {
                    for(int j=0;j<matchTag.Length;j++)
                        ignoreIndexes.Add(matchTag.Index + j);
                }
            }

            for (int j = 0; j < lineLength; j++)
                if (!ignoreIndexes.Contains(j))
                    lineVertexStartIndex.Add((lineStart+j)*6);

            linesVertexIndexes.Add(lineVertexStartIndex);
        }
        return linesVertexIndexes;
    }
	
	//获取行偏移比例参数
    float GetAlignmentFactor()
    {
        switch (alignment)
        {
            default:
                Debug.LogError("Invalid Convertions Here!");
                return 0;
            case TextAnchor.UpperLeft:
            case TextAnchor.MiddleLeft:
            case TextAnchor.LowerLeft:
                return 0;
            case TextAnchor.UpperCenter:
            case TextAnchor.MiddleCenter:
            case TextAnchor.LowerCenter:
                return .5f;
            case TextAnchor.UpperRight:
            case TextAnchor.MiddleRight:
            case TextAnchor.LowerRight:
                return 1f;
        }

    }
}

2.编辑器脚本(便于编辑器配置数据,放到Editor文件夹下)

[CustomEditor(typeof(UIT_TextExtend)),CanEditMultipleObjects]
public class EUITextExtend : UnityEditor.UI.TextEditor
{
    UIT_TextExtend m_target = null;
    public override void OnInspectorGUI()
    {
        m_target = target as UIT_TextExtend;

        EditorGUILayout.BeginHorizontal();
        int spacing = EditorGUILayout.IntField("Character Spacing:", m_target.m_characterSpacing);
        if (spacing != m_target.m_characterSpacing)
        {
            Undo.RecordObject(m_target,"Character Spacing");
            m_target.m_characterSpacing = spacing;
            m_target.SetAllDirty();
        }
        EditorGUILayout.EndHorizontal();

        base.OnInspectorGUI();
    }
}
感谢耐心看完这篇文章 如遇任何问题请联系博主
                                                                    --StriteR. 2020.5.30

你可能感兴趣的:(开发工具)