UNITY3D UGUI 字间隔
项目有遇到Text字间隔的问题 可惜ugui原生不支持 参考网络上的脚本做了一版
效果
思路
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 = @"<b>|</b>|<i>|</i>|<size=.*?>|</size>|<Size=.*?>|</Size>|<color=.*?>|</color>|<Color=.*?>|</Color>|<material=.*?>|</material>";
//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();
}
}
|