UI字体
- 避免字体框重叠,造成合批打断
- 字体网格重建
- UIText组件发生变化时
- 父级对象发生变化时
- UI组件或其父对象enable/disable时
UI字体 资源导入时的设置
TrueTypeFontImporter
- 支持TTF和OTF字体文件格式导入
- Font Size:字体大小,是基于文字处理程序设置的大小
- Rendering Mode:使用哪种字体渲染的平滑模式。默认使用Smooth就好,这种是在动态字体上最快的一种模式
- Character:导入字体文件选择哪个字符集
- Dynamic:在运行时渲染字体字形
- Unicode:代表选择Unicode字符集
- ASCII default set:代表选择ASCII码字符集
- ASCII Upper Case:代表选择ASCII码中的大写字符集
- ASCII Lower Case:代表选择ASCII码中的小写字符集
- Custom Set:代表自定义选择字符集,选择这个选项时,我们可以从导入的字体文件中选择我们想要的字符
- 除第一种Dynamic外,其他5种都是静态字符集
- 接下来的几个选项都是字符边界的选项,一般默认就好
- Include Font Data:
- 勾选时一般适合动态字体属性一起使用。
- 当选中复选框后,导入的TTF或OTF文件会随APP文件构建一起输出;如果没有勾上该选项则不会随APP一起输出。
- 如果使用的是对应操作系统中已有的字体,不勾此选项则可以节省内存与输出包大小;如果目标文件中没有该字体,则会在下面Font Name选项列表中选择一种后备字体使用。
- 也可以使用References to other fonts in project选项中指定的其他项目内的字体作为后备字体
- 支持TTF和OTF字体文件格式导入
当然我们还可以使用Unity编辑器中的Custom Font或通过TextMeshPro中的Font Asset Creator工具创建自定义式样的静态字体资源
选择Dynamic字符集后使用动态字体或字体图集需要了解的一些细节:
- 字体图集会按2的幂次大小进行扩大,图集大小只增不减(512x512 -> 512x1024),运行时,这会对我们的效率产生一定影响,所以在预加载或启动时,我们可以通过Font。RequestCharacterInTexture接口将运行时需要的字体提前加入到图集中,这样可以有效地减少启动时间或运行时字体图集动态扩展的时间
建议将TextMeshPro作为Unity文字处理的最佳方案
- TMP使用有向距离场(Signed Distance Field 简称SDF)作为文本的渲染管道,可以以任意点大小和分辨率清晰地渲染文本,并在一些视觉特效上使用材质预设来处理,如轮廓、阴影、倒角、光晕等效果,而且效率更高
- 超采样:加大FontSize,减小Scale
- 简单地说:TMP记录的是一个字体的矢量形状,渲染时通过矢量方式来进行渲染,因此无论如何放大缩小它的清晰度都是不会改变的。这也就是TMP最大的优点
- 将Scene视图中的显示模式改为Overdraw(显示当前图像在屏幕中的填充率)后如下图所示:
- 在同样的屏幕范围内渲染多次就会产生overdraw,可以发现TMP基本不会出现重叠部分。在一般渲染情况之下已经比Text有一定的优势了
- 假如在Text上面添加一个描边组件如下图所示:
- 因为描边,它渲染了四次,对于屏幕填充率的占用,它的性能非常差
- 而使用TMP,只需对材质上的描边厚度进行添加,就完成了描边
- 因为本身TMP使用SDF有向距离场的方式来进行渲染的时候,它在渲染之前就已经把这个描边给计算出来了
- 因此TMP组件在性能上远远超过Text组件
- 缺点:
- 选中对应的材质。我们每次使用TMP,都会对现有的资源里的贴图进行修改,而这个贴图所占的空间是比较大的
- 在贴图被填满后假如不勾选Multi Atlas Textures(使用多张贴图)的话,新的字会显示不出来(显示口字)。为了避免这个问题,一般会选到4096x4096,并且勾选Multi Atlas Textures,同时减小Sampling Point Size到60、Padding到6(取样大小)
UI控件优化的注意事项
首先,不需要交互的UI元素,一定要关闭Raycast Target选项
一定要使用OnDemandRendering接口降频,而不是直接调整TargetFPS。两者的区别是,OnDemandRendering接口只会降渲染频率不会降输入频率,而TargetFPS接口会渲染和输入一起降
滚动视图Scroll View
- 首先,它是个容器,需要大量实例化子对象控件,子对象控件简单点还好,如果过于复杂会有效率问题。不光对象大量实例化开销,由于视图滚动还要触发UI的Rebuild开销。这时我们需要做两个工作来进行优化:
- 使用RectMask2d组件裁剪,通过模板缓冲剔除不必要的渲染。注意不要使用不规则的滚动视图,因为RectMask2d没有使用模板缓冲,而直接使用Rect相交检测去裁剪,如果是不规则形状则需要PixelMask写额外的Shader来做剔除,这样会有额外的渲染开销
- 可以通过可视化位置构建子元素对象池,以减小内存与实例化的开销。这里的内存池是根据子对象的渲染位置来做的内存池,而不是对所有子对象做的内存池