首页 > 其他分享 >Text和TextMeshPro

Text和TextMeshPro

时间:2023-12-26 20:12:47浏览次数:34  
标签:贴图 字符 Text TextMeshPro 字体 文本 图集

参考文章:

1.关于TextMeshPro | (ttthyy.com)

2.[UGUI图文混排一]TextMehPro(TMP)使用手册 - 知乎 (zhihu.com)

1.Text

1.原理:

Text会根据所给定的字符串生成相关的图集,然后对图集进行采样就可以渲染出文字了。文本字形是作为独立的面片(quad)进行渲染的,每个字符都是一个面片。

OnPopulateMesh(会在Rebuild时调用)

为CanvasRender的Mesh提供顶点位置、顶点颜色、UV和三角形信息

1.根据组件的配置生成一个TextGenerationSettings,用来生成后面的信息。

2.调用TextGenerator.PopulateWithErrors生成Mesh的顶点、顶点颜色、UV和三角形信息。

3.计算偏移量(例如左对齐需要紧靠左边),最后遍历TextGenerator的顶点数组,将它们的位置除以pixelsPerUnit(每单元像素)并加上偏移量(如果有的话),得到的结果填到VertexHelper(可以拿到顶点信息)

2.字符图集

被加载的每个不同的Font对象都会维护自己的纹理集。在Unity的实现中,这些字体在运行时根据Text组件中出现的字符构建一个字形图集(glyph atlas)。

动态字体为每种不同的结合(尺寸、样式、字符)在其纹理集中维护了一个字形。也就是说,如果一个UI中有两个Text组件,都显示了字符“A”,那么

  • 如果两个Text组件尺寸相同,那么字体图集中会有一个字形。
  • 如果两个Text组件尺寸不同,那么字体图集中会有两个不同尺寸的字母“A”。
  • 如果一个Text组件的样式是粗体而另一个不是,那么字体图集中会含有一个粗体的“A”和一个普通的“A”。  

当使用动态字体的Text对象遇到了字体纹理集(对应字符图集)中没有的情况,必须重建字体纹理集

如果新的字形能够加入当前图集,那么将其加入图集并上传到图形设备。

但是如果当前的图集放不下,那么系统会尝试重建图集。重建图集的过程:

1.尝试回收掉不用的字符:以相同的大小重建图集,只使用当前活动的Text组件上显示的字形。

2.回收后还是放不下就要扩容:例如,一个512x512的图集或被扩充到512x1024的图集。

所以,为了避免频繁的重建字符图集,Text使用的字符最好在使用前就填充到字符图集中

分为两种情况:

1.如果使用的字体仅需要支持部分字符集(比如只需要几个固定的字),那就可以使用非动态字体并预先配置对想要使用的字体集的支持。

2.字符集不固定或者很多(比如整个Unicode集合),那么字体必须设为动态,可以将出现频率高的字符在游戏运行时填充(使用Font.RequestCharactersInTexture)。

3.使用静态字体集

https://blog.csdn.net/qq_29867963/article/details/77680033

4.支持回滚系统字库

在遇到选择的字体字库没有的字的情况,可以自动使用系统的字库,可以避免生僻字不渲染的情况。

5.缺点

1.由于使用的是点阵字贴图(贴图存的是颜色值),所以放大缩小文本(更改scale)会使字体编的模糊。

 

2.前面提到了Text的动态图集是增量式扩大,这种方式在文本量很小的情况下贴图很小,很舒服,但随着文本量的增加,会频繁的发生重建以及扩容,可能会引起卡顿。

3.前面提到了字符图集是按Text组件的设置存储的,所以会出现下面的情况:

 这些字块贴图会占用整张文本贴图的空间,导致过快的撑满一张贴图,引起扩大重建。而且字号很大的Text所生成的贴图也很大,很占空间,这也是提倡不要使用Text组件BestFit功能的一个主要原因,BestFit功能会造成文本字号的不可控,导致创建出许多不同字号的字块贴图。。

4.功能限制:不支持富文本标签的全部功能、也不支持所有的文本效果,而且一些文本效果实现很费(描边、阴影等都是通过增加顶点并偏移的方式,正常项目中很少会用到)。

2.TextMeshPro

作为Unity的最终文本解决方案,除了支持图文混排,它还支持矢量字体,可以很好的替代旧版的Text组件。

针对Text的缺点,做出了如下改进

1.使用矢量字(SDF算法)。

这种实现方式不会出现缩放时的失真并且不会根据不同的字号创建不同的贴图(毕竟不会失真)

SDF算法简述

对于字块贴图上记录的不是像素的颜色信息,而是每个像素到字形边缘的距离,当文本放大缩小时,TextMeshPro对像素到字形边缘的距离进行插值,而不是对颜色插值,也就是说此处得到的一个字形的轮廓区域,并没有马上得到每个像素的颜色,如果用01来表示的话,相当于就是把落在字块上的像素全部标1,然后再进行上色。这样就不存在对颜色插值不准确造成的失真问题,因为对距离的插值总是可以得到一个清晰的字形轮廓

2.解决字符贴图重建的问题

1.每个字体要创建对应的字体资源文件

这个文件可以是动态渲染模式或者是动态渲染模式(和Text差不多),在这个文件中配置生成的字符贴图的设置:
动态:

 静态:

 当创建的字符贴图尺寸超过配置的Atlas Width 与 Atlas Height时就不会再继续加入字符了(显示成方块),可以勾选Multi Atlas Textures来允许创建多张贴图(会打断合批)

 2.字体回滚

TextMeshPro字体允许设置一个回滚字体(注意此处的回滚与上面的Dynamic模式回滚ttf模式不同),当本字体中缺少字符时,可以从设置的回滚字体列表(同样都是TextMeshPro字体)中查找需要的字符。

 

基于这些特性,可以很好的解决Text中关于大贴图重建的问题。

可以创建一个包含常用文字的静态字体,并设置一个回滚TextMeshPro字体(动态字体、贴图尺寸不宜过大(降低重建贴图的开销),并勾选Multi Atlas Textures)。这样,一般使用的时候从静态字体中获取字块,若静态字体中缺少字块时,从动态字体中加载。 可以解决 静态字体字符数过多导致初始加载过大的问题,以及使用动态回滚字体时,重建贴图过大的问题,允许使用多张贴图,将重建一张大贴图的开销拆分到重建小图中(需要权衡一下是要内存小还是能合批)。

4.对富文本和文字效果很友好

1.支持图文混排

设置SpriteAsset,并用富文本引用

2.文字效果

描边、阴影等效果都是使用Shader实现的,相比于原生的Text组件通过增加顶点偏移的方式,渲染效果更好,并且效率也更高。但一般项目应该都自己实现过了,对新项目比较友好。

5.缺点

1.SDF算法的性能

生成SDF图的算法简单说就是求每个像素点到文字的最短路径的动态规划(不确定textmeshpro有没有做比较牛逼的优化,网上说是8ssedt)。

如果高分辨率下动态生成字符图集,像素点数量很多,并且一次要添加的字符很多,可能会卡(没测过),正常情况下不会。

2.DrawCall

文字效果是通过不同的Material实现的,添加一个新的特效文字,步骤:

先调整好需要的特效、然后点击Create Material Preset 创建一个新的Material。

 在实际开发中,可能会用到很多种不同效果的字体,这将会导致需要创建大量材质球,增加DrawCall

3.堆内存

创建100个Text(TMP),可以看到它的GC Alloc达到了1.8MB。不使用TMP,那创建100个Text呢?经过测试,产生的GC是1.0MB。

 其中TextMeshProUGUI的Awake、OnEnable和.ctor都产生了大量的GC。查看代码可知,主要原因是由于 TMP_Text 和 TMP_TextInfo 在创建时预创建了较多的数组变量,导致申请了较大的堆内存,另一方面,数组变量在中间使用的过程,存在Resize操作,又会产生新的堆内存申请。

为了优化这个问题,大家可以根据实际需要,将原先申请的内存缓存起来,在下一次创建的时候重新拿起来使用,避免每次都重新申请。

标签:贴图,字符,Text,TextMeshPro,字体,文本,图集
From: https://www.cnblogs.com/mcyushao/p/17927040.html

相关文章

  • Sublime Text 4汉化
    1知识小课堂1.1sublim简介Sublime是一款代码编辑器,致力于为开发人员提供快速、高效、特性丰富的代码编辑环境。它支持多种编程语言,包括但不限于Python、JavaScript、Ruby、HTML、CSS等。Sublime拥有一套强大的插件系统,允许开发人员自定义编辑器的外观和行为,包括自动完成、语法高......
  • 实现ApplicationContextAware没有生效
    下面这段代码是存在一个spring-boot-starter中,引入到其他项目中,启动后获得不到ApplicationContext,原因是启动类中,没有扫描到对应路径:增加代码:@ComponentScan(value="com.XXX.common.project")代码如下@ServicepublicclassSpringContextHolderimplementsApplicationCont......
  • C# RichTextBox的上标及文字大小
    C#RichTextBox进行上下标的处理,单纯的文本控件TextBox满足不了这个功能,必须使用RichTextBox富文本控件来实现,具体效果如下:未设置上标字体大小前:设置上标的字体大小后: 具体的代码如下:this.richTextBox1.SelectedText="mm";this.richTextBox1.......
  • MySql对表加字段( You have to change some columns to TEXT or BLOBs)
    对MySql中表增加字段,发现提示报错:1、首先了解下字符集不同字符集下,占用空间不一样gbk编码中,1个字符占用2个字节utf8编码(默认)中,1个字符占用3个字节utf8mb4编码中,1个字符占用4个字节varchar除了存储字符,还需要额外的空间来存储长度和是否为NULL,分别占用1-2字节和1字节2、行大小限制 ......
  • NOI Linux Sublime Text 使用指南
    感觉noilinux的vscode还是太鸡肋,所以用了用subline,莫名好用下面是食用指难。首先打开,不好看,我们可以点击这里更改相应主题然后我们要点file打开文件夹打开/关闭侧边栏的快捷键是Ctrl+K+B(K和B同时按)然后sublime不能输入,直接用文件输入输出。所以这样的分屏比较优......
  • Java登陆第二十九天——ServletConfig和ServletContext
    ServletConfigServletConfig是web.xml中,Servlet的初始化参数对象(每个Servlet都有一个ServletConfig对象)web.xml<?xmlversion="1.0"encoding="UTF-8"?><web-appxmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://ww......
  • react Hooks+Context 实现响应式布局
    1.创建文件 viewportContext.tsx importReactfrom"react";constdefaultValue={  width:window.innerWidth}constviewportContext=React.createContext(defaultValue);constViewportProvider=({children})=>{  const[width,setWidt......
  • 解密视频魔法:将ExternalOES纹理转化为TEXTURE_2D纹理
    在使用OpenGLES进行图形图像开发时,我们常使用GL_TEXTURE_2D纹理类型,它提供了对标准2D图像的处理能力。这种纹理类型适用于大多数场景,可以用于展示静态贴图、渲染2D图形和进行图像处理等操作。另外,有时我们需要从Camera或外部视频源读取数据帧并进行处理。这时,我们会使用GL_TEXT......
  • updatetext关键字应用简介说明
    updatetext功能说明:updatetext的功能为:更新当前的text,ntext,image字段,当我们可以使用updatetext更新列中的部分数据updatetext语法简介: -----参数说明-------------------------BULK:是否采用二进制数据流,非采用二进制数据流,此参数无需输入table_name.dest_column_......
  • 记录一次openpyx使用rich_text报错AttributeError: 'TextBlock' object has no attrib
    先说解决办法:pipinstalllxml报错截图:当时在两个环境中分别使用相同版本openpyxl,相同的代码,一个环境中能成功,另外一个一直报错。排查结果如下:根据报错找到文件:File"\openpyxl\worksheet_writer.py",line147,inwrite_row在155行到158行看到如下代码:ifLXML:......