UGUI中随意调整Text中的字体间距

小编 2026-06-18 阅读:1289 评论:0
UGUI中是没有可以随意调整字体间的距离的方法,仔细研究一下可以通过控制每个字体的网格顶点位置进行调整字体之间的距离, 分析一下最简单情况:输入的文本是单行的,且末尾没有换行符; unity在...

UGUI中是没有可以随意调整字体间的距离的方法,仔细研究一下可以通过控制每个字体的网格顶点位置进行调整字体之间的距离,
分析一下最简单情况:输入的文本是单行的,且末尾没有换行符;
unity在UnityEngine.UI命名空间中定义了一个BaseMeshEffect抽象类,他提供了一个抽象方法ModifyMesh(VertexHelper vh),使得可以轻松地获得text文本中所有字体 的顶点信息,我们的移动字体的操作将在这里面进行。VertexHelper类主要是用于提供字体网格数据的工具类;
\"在这里插入图片描述\"

上述便是挂载TestSpacingText脚本之后的效果图。下面贴出代码

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

public class TextSpacingTest : BaseMeshEffect
{
    public float spacing = 0;
    public override void ModifyMesh(VertexHelper vh)
    {
        List<UIVertex> vertexs = new List<UIVertex>();
        vh.GetUIVertexStream(vertexs);
        int vertexIndexCount = vertexs.Count;
        for (int i = 6; i < vertexIndexCount; i++)
        {
            UIVertex v = vertexs[i];
            v.position += new Vector3(spacing * (i / 6), 0, 0);
            vertexs[i] = v;
            if (i % 6 <= 2)
            {
                vh.SetUIVertex(v, (i / 6) * 4 + i % 6);
            }
            if (i % 6 == 4)
            {
                vh.SetUIVertex(v, (i / 6) * 4 + i % 6 - 1);
            }
        }
    }
}

分析代码:
1)首先创建一个字体间距的变量,然后需要继承BaseMeshEffect类并且实现其中的抽象的方法MeshModify()函数。
2)创建一个容器从网格信息生成器vh中将字体的顶点信息全部加载保存下来
3)接下来开始遍历获取到的顶点,我们知道每个字体是由两个三角形的组成的网格,字体是显示在这样的网格上的,因此每个字体也就对应6个顶点。那么就开始移动每个顶点就可以了。
4)移动顶点之后要记得设置UV顶点与顶点索引的对应关系,因为一个字体网格由两个三角形组成,那么就重叠了两个顶点,故而一个字体的6个顶点,就只对应4个UV顶点索引,如上代码显示的那样。
分析如下:
\"在这里插入图片描述\"

接下来看看比较复杂的情况:
文本的情况为,可以有多行,或单行,单行、多行时末尾均可以有换行符。
核心思路:
1)先考虑仅仅是多行且末尾行的末尾没有换行符的情况,解决了这个核心问题,再考虑其他的问题。
2)将多行的文本按照换行符进行分割,这样每一行就形成了一个字符串,此时对每一行进行上面简单的操作,就可以实现移动的了。
3)考虑到所有的文本的顶点信息数据都存储在vh中,可以创建一个行数据结构Line以此来存储每行的基本属性(比如:本行开始定点的索引位置,结束顶点的索引位置,所有顶点的数量)。
4)简单多行的情况,利用上面的分行的思路就可以解决,接下来分析其他的问题。
5)单行时末尾有换行符,我们在分割字符串之后要加以判断是否有空串的情况 ,若有那么就认为末尾产生了换行符,此时空串不再创建LIne对象,只用创建一个Line对象。解法看代码。
6)多行时末尾有换行符,同样用于上面一样的方法进行检验,最后一个空串不在创建Line对象,解法看代码。
7)之后若是想扩展修改字体垂直方向的间距也可以在此基础上修改,非常简单。
接下来看代码:

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


internal class Line
{
    //每行开始顶点索引
    private int startVertexIndex;
    public int StartVertexIndex
    {
        get
        {
            return startVertexIndex;
        }
    }

    //每行结束顶点索引
    private int endVertexIndex;
    public int EndVertexIndex
    {
        get
        {
            return endVertexIndex;
        }
    }

    //每行顶点总量
    private int countVertexIndex;
    public int CountVertexIndex
    {
        get
        {
            return countVertexIndex;
        }
    }

    public Line(int startVertexIndex,int countVertexIndex)
    {
        this.startVertexIndex = startVertexIndex;
        this.countVertexIndex = countVertexIndex;
        this.endVertexIndex = this.startVertexIndex + countVertexIndex - 1;

    }
}

/// <summary>
/// 这是设置字体移动的核心类
/// 执行多重行移动的核心算法是:将多重行分开依次进行处理,每一行的处理都是前面对单行处理的子操作
/// 但是由vh是记录一个文本中所有的字的顶点,所以说需要分清楚每行开始,每行结束,以及行的字个数,
/// 如此需要创建一个行的数据结构,以保存这些信息
/// </summary>
public class TextSpacingMulTest : BaseMeshEffect
{
    public float spacing = 0;
    public override void ModifyMesh(VertexHelper vh)
    {
        Text text = GetComponent<Text>();
        string[] ls = text.text.Split(\'\\n\');
        int length = ls.Length;
        bool isNewLine = false;
        Line[] line;
        if (string.IsNullOrEmpty(ls[ls.Length - 1]) == true)
        {
            line = new Line[length - 1];
            isNewLine = true;
        }
        else
        {
            line = new Line[length];
            
        }
        //Debug.Log(\"ls长度\" + ls.Length);
        for (int i = 0; i < line.Length; i++)
        {
            if (i == 0 && line.Length == 1&&isNewLine==false)//解决单行时没有换行符的情况
            {
                line[i] = new Line(0, ls[i].Length * 6);
                break;
            }
            if (i == 0&&line.Length>=1)//解决单行时有换行符的情况,以及多行时i为0的情况
            {
                line[i] = new Line(0, (ls[i].Length+1) * 6);
            }
            else
            {
                if (i < line.Length - 1)
                {
                    line[i] = new Line(line[i - 1].EndVertexIndex + 1, (ls[i].Length + 1) * 6);
                }
                else
                {
                    if (isNewLine == true)//解决多行时,最后一行末尾有换行符的情况
                    {
                        line[i] = new Line(line[i - 1].EndVertexIndex + 1, (ls[i].Length + 1) * 6);
                    }
                    else
                    {
                        line[i] = new Line(line[i - 1].EndVertexIndex + 1, ls[i].Length * 6);
                    }
                }
            }
        }

        
        List<UIVertex> vertexs = new List<UIVertex>();
        vh.GetUIVertexStream(vertexs);
        int countVertexIndex = vertexs.Count;
        //Debug.Log(\"顶点总量\" + vertexs.Count);
        for (int i = 0; i < line.Length; i++)
        {
            if (line[i].CountVertexIndex == 6) { continue; }
            for (int k = line[i].StartVertexIndex+6; k <= line[i].EndVertexIndex; k++)
            {
                UIVertex vertex = vertexs[k];   
                vertex.position += new Vector3(spacing * ((k-line[i].StartVertexIndex) / 6), 0, 0);
                //Debug.Log(\"执行\");
                vertexs[k] = vertex;
                if (k % 6 <= 2)
                {
                    vh.SetUIVertex(vertex, (k / 6) * 4 + k % 6);
                }
                if (k % 6 == 4)
                {
                    vh.SetUIVertex(vertex, (k / 6) * 4 + k % 6 - 1);
                }
            }

        }


    }
}

版权声明

本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。

热门文章
  • 机房智能化温湿度解决方式之POE供电以太网温湿度传感器

    机房智能化温湿度解决方式之POE供电以太网温湿度传感器
    机房智能化温湿度解决方式之POE供电以太网温湿度传感器 北京盈创力和电子科技有限公司 智能型TCP网口温湿度记录仪 北京IP网络温湿度记录仪厂家,北京盈创力和 北京智能型TCP网口温湿度记录仪IP网络温湿度记录仪是一种新型的基于TCP/IP协议双绞线以太网标准温湿度采集模块,利用它可以实现现场温度值、相对湿度值的采集,同时利用其自身的RJ45通信接口可以方便地和机房监控主机或交换机集线器进行联网。 工作于-40℃~85℃工业级带...
  • Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering

    Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering
    Problem Statement 我们考虑一个具有马尔可夫性质、非线性、非高斯的状态空间模型(State Space Model):对于一个时间序列上的观测结果{yt,t∈N}\\{ y_t , t \\in N \\}{yt​,t∈N},我们认为每个观测结果yty_tyt​的生成依赖于一个无法直接观察的隐变量xt∈{xt,t∈N}x_t \\in \\{x_t , t \\in N \\}xt​∈{xt​,t∈N},即:p(...
  • HTTP状态保持的原理

    HTTP状态保持的原理
    a)在用户登录之后,浏览器返回响应的时候会在响应中添加上cookieb)浏览器接收到cookie之后会自动保存c)当用户再次请求同一服务器中的其他网页的时候,浏览器会自动带上之前保存的cookied)服务接收到请求之后可以请 request 对象中取到cookie 判断当前用户是否登录  Http是无状态的,就是连接时数据互通,关闭后...
  • Hive 系统函数及示例

    Hive 系统函数及示例
    查看所有系统函数 show functions; 函数分类 内置函数【系统函数】 数学函数: floor、round、ceil、cos、log2等 字符串函数: length、reverse、trim、lower、get_json_object、repeat等 收集函数: size 转换函数: cast 日期函数: year、month、datediff、date、date_add等 条件函数: coalesce、case…w...
  • CSRF的原理和防范措施

    CSRF的原理和防范措施
    a)攻击原理:i.用户C访问正常网站A时进行登录,浏览器保存A的cookieii.用户C再访问攻击网站B,网站B上有某个隐藏的链接或者图片标签会自动请求网站A的URL地址,例如表单提交,传指定的参数iii.而攻击网站B在访问网站A的时候,浏览器会自动带上网站A的cookieiv.所以网站A在接收到请求之后可判断当前用户是登录状态,所以...
标签列表