关于构建体积、字体、字形图集与运行时性能的直接解答——提炼自真实开发者的提问。
不会。UniText 不会把逐字体的纹理图集烘焙进您的构建。字形是在运行时被光栅化到一个共享图集(基于 Texture2DArray),并带有逐字形的引用计数和 LRU 淘汰。只有字体数据会随构建一起发布——图集从不会。此外,内置的字体压缩(Zstd,级别 22)可将拉丁文/阿拉伯文的字体数据缩小至多约 ~2.7×(CJK 幅度较小,约 ~1.3×)。
不需要。UniTextFont 资源会把字体字节内嵌在自身之内。对源字体的引用仅限编辑器(包裹在 #if UNITY_EDITOR 中)——它在播放器构建中根本不存在,因此不是运行时依赖,也不会通过依赖查找被拉进 AssetBundle。资源一旦创建完成,您就可以删除 .ttf。
不需要。您可以通过 UniText 工具窗口,从磁盘上任意位置的 .ttf 构建一个 UniTextFont(文件对话框会直接读取字节)。把字体导入项目是可选的。
• WebGL:空构建 ≈ 6–10 MB(具体取决于 Unity 版本和已安装的包);UniText 会加入它的原生库(HarfBuzz、FreeType)。这些正是 Unity 自家 UI Toolkit Advanced Text Generator 所附带的同一批行业标准库——没有任何冷门东西(UniText 只是自带了它自己的副本)。 • Android:一个包含两种架构的 APK 会同时携带两者——每种架构约 +4 MB。但当您发布 AAB 时,Google Play 会交付针对具体设备的包,因此用户只下载自己的那一种架构(~4 MB),而非两者。
仅当某个字形尚未在图集中时——绝不是每帧。对于 “Hello world”,它会光栅化各不相同的字形 H e l o w r d。第二个 H 什么都不做;一个 a 就只光栅化那个 a。
开销与那一帧中被光栅化的、各不相同且首次出现的字形数量成正比——而与文本的长度无关。在我们的基准测试中,第一帧 ~2000 个各不相同的字形,在一台典型的 Android 设备上约 ≈ 1 秒;同样的场景下,TMP 和 UI Toolkit 要花 10+ 秒。复用已缓存的字形则是免费的。
在热路径上,UniText 几乎不依赖 Unity Job System——这是刻意的设计。字形光栅化(我们自研的 lpSDF / lpMSDF)默认通过计算着色器(compute shader)在 GPU 上运行;Burst job 只是在无法使用计算着色器时的 CPU 回退方案。主要的多线程——塑形、布局、网格生成——运行在 UniText 自有的操作系统线程池上(并非 Unity Jobs,这正是它们不会出现在 Jobs profiler 中的原因)。所以“看不到 UniText 的 job”并不意味着“线程关掉了”:要么工作交给了 GPU,要么图集已经预热,要么文本低于并行阈值(短标签或单个标签会被顺序处理——那样更省)。
“Update() 很慢”对于发布构建而言是个误区。从原生代码调用魔法方法的开销确实存在,但可以忽略不计(~1000 次调用 ≈ 0.16 ms)——它不是瓶颈。朴素代码中真正的开销是 AoS 内存布局,而非回调本身;UniText 在关键处采用 SoA(Unicode 属性、度量、逐像素缓冲区)。(这也是 ECS 快的原因——归功于 SoA,而非“ECS 魔法”。)况且 UniText 本来就是集中式的——只不过不是以 MonoBehaviour 管理器的形式:Update() 本身几乎是空的,而繁重的工作被汇集到 Canvas 渲染回调上的单次批处理过程中(这也是它实现跨组件并行的原因)。