Unity中画下划线——通过顶点渲染来实现 可换行渲染

通过顶点渲染来实现 可换行渲染

在做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组件)

以上代码为半原创内容,有借鉴大佬的代码也有自己加工的代码。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值