通过顶点渲染来实现 可换行渲染
在做UI的时候有一种需求是画下划线,下面的代码是Unity2019版本下编写的“画下划线”的方法,该方法改写了大大的下划线方法(可能版本不一样,导致大佬的代码不能直接拿过来用)大佬的文字如下:
链接:一个博客里面的代码
链接:在CSDN中相同的代码
以上的内容的一样我不知道谁是原创所以都放出来了(我的代码是改写过的代码,因为我复制粘贴用不了来着)
下面的代码是我改写和完善的代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.UI;
using System;
public class TextUnderLine : Text
{
private float distance = 0f;
private float lineHeight = 4f;
private Color UnderLineColor;
private bool Special = false;
private List<UIVertex> m_vertexs = new List<UIVertex>();
private int m_start = 0;
private int m_end = 0;
protected override void OnPopulateMesh(VertexHelper toFill)
{
base.OnPopulateMesh(toFill); //渲染text字体的顶点
toFill.GetUIVertexStream(m_vertexs); //toFill创建vertex流
if (m_vertexs.Count <= 0) return;
SetUnderLine(toFill);
}
private void SetUnderLine(VertexHelper vh) {
if (m_end <= 0) m_end = m_Text.Length-1;
List<int> lineStart = new List<int>();
List<int> lineEnd = new List<int>();
Dictionary<int,int> lineFeed = new Dictionary<int,int>();
SaveLinePos(ref lineStart, ref lineEnd);
SaveLineFeed(ref lineFeed, lineStart, lineEnd);
if (lineFeed.Count < 1)
{
Vector2 startPos = new Vector2(m_vertexs[lineStart[0]].position.x, m_vertexs[lineStart[0]].position.y);
Vector2 endPos = new Vector2(m_vertexs[lineEnd[lineEnd.Count - 1]].position.x,
m_vertexs[lineEnd[lineEnd.Count - 1]].position.y);
MeshUnderLine(vh, startPos, endPos);
}
else
{
int pos = 0;
Vector2 startPos = new Vector2();
Vector2 endPos = new Vector2();
foreach (KeyValuePair<int, int> kvp in lineFeed) {
startPos = new Vector2(m_vertexs[lineStart[pos]].position.x, m_vertexs[lineStart[pos]].position.y);
endPos = new Vector2(m_vertexs[kvp.Value].position.x, m_vertexs[kvp.Value].position.y);
pos = kvp.Key + 1;
MeshUnderLine(vh, startPos, endPos);
}
startPos = new Vector2(m_vertexs[lineStart[pos]].position.x, m_vertexs[lineStart[pos]].position.y);
endPos = new Vector2(m_vertexs[lineEnd[lineEnd.Count - 1]].position.x,
m_vertexs[lineEnd[lineEnd.Count - 1]].position.y);
MeshUnderLine(vh, startPos, endPos);
}
}
private void SaveLineFeed(ref Dictionary<int,int> lineFeed, List<int> lineStart, List<int> lineEnd) {
for (int i = 0; i < lineStart.Count-1; i++) {
float distance = Math.Abs(m_vertexs[lineStart[i]].position.y - m_vertexs[lineStart[i + 1]].position.y);
if (distance >= fontSize && distance < fontSize *2){
lineFeed.Add(i,lineEnd[i]);
}
}
}
private void SaveLinePos(ref List<int> lineStart, ref List<int> lineEnd) {
for (int i = m_start; i <= m_end ; i++) {
int minPos = i* 6;
int maxPos = i * 6;
for (int j = i * 6; j < (i + 1) * 6 - 1; j++)
{
if (m_vertexs[minPos].position.x > m_vertexs[j].position.x)
{
minPos = j;
}
else if (m_vertexs[minPos].position.x == m_vertexs[j].position.x && m_vertexs[minPos].position.y > m_vertexs[j].position.y)
{
minPos = j;
}
if (m_vertexs[maxPos].position.x < m_vertexs[j].position.x)
{
maxPos = j;
}
else if (m_vertexs[maxPos].position.x == m_vertexs[j].position.x && m_vertexs[maxPos].position.y > m_vertexs[j].position.y)
{
maxPos = j;
}
}
lineEnd.Add(maxPos);
lineStart.Add(minPos);
}
}
private void MeshUnderLine(VertexHelper vh, Vector2 startPos, Vector2 endPos)
{
Vector2 extents = rectTransform.rect.size;
var setting = GetGenerationSettings(extents);
TextGenerator underlineText = new TextGenerator();
underlineText.Populate("—", setting);
if (distance > fontSize && lineHeight > font.fontSize) {
Debug.LogError("UnderLine property is Error! please make Certain property can't greater than fontSize.");
return;
}
IList<UIVertex> lineVer = underlineText.verts;/*new UIVertex[4];*///"_"的的顶点数组
Vector3[] pos= new Vector3[4];
pos[0] = startPos + new Vector2(-8, -distance);
pos[3] = startPos + new Vector2(-8, -(distance + lineHeight));
pos[2] = endPos + new Vector2(8, -(distance + lineHeight));
pos[1] = endPos + new Vector2(8, -distance);
Color tempColor = Special ? UnderLineColor : color;
UIVertex[] tempVerts = new UIVertex[4];
for (int i = 0; i < 4; i++) {
tempVerts[i] = lineVer[i];
tempVerts[i].color = tempColor;
tempVerts[i].position = pos[i];
tempVerts[i].uv0 = lineVer[i].uv0;
tempVerts[i].uv1 = lineVer[i].uv1;
tempVerts[i].uv2 = lineVer[i].uv2;
tempVerts[i].uv3 = lineVer[i].uv3;
}
vh.AddUIVertexQuad(tempVerts);
}
public void SetUnderLinePos( int start, int end) {
m_start = start - 1;
m_end = end - 1;
}
public void SetUnderLinePos(int start) {
m_start = start - 1;
m_end = m_Text.Length-1;
}
public void SetUnderLineColor(Color color) {
UnderLineColor = color;
Special = true;
}
public void SpecialInit(float underLineHeight, float underLineDistance)
{
distance = underLineDistance;
lineHeight = underLineHeight;
}
}
可以通过调用SetUnderLineColor() 方法设置下滑线的颜色,默认情况下与字体的颜色相同
SpecialInit()方法主要是设置下划线的粗细(underLineHeight)和距离字体的高度(underLineDistance)
该方法是直接作为一个组件使用的,只需要直接挂在到游戏物体上(不能有Text组件)
以上代码为半原创内容,有借鉴大佬的代码也有自己加工的代码。