14 种语言、一个程序员,还有一个只在玩家切换语言时才冒出来的内存尖峰。Soft Crunch Games 没有靠猜,而是靠剖析分配路径找到了它:静态图集里没有的字形会在运行时被光栅化,塞进超大的 4096 乘 4096 回退图集,而每个新字形都会触发一次完整 16 MB 的图集重传。修复办法并不花哨,但很有效:把回退字体重新生成为 2048 乘 2048 的页面,并在切换语言之前批量加入字形,日文新增图集内存就从约 48 MB 降到了每字体 4-8 MB。
现象:支持 14 种语言的 Foxy Dumplings 在切换语言时出现内存尖峰
根因:静态图集缺失的字形在运行时被塞进超大的 4096 乘 4096 回退图集,每个新字形触发一次完整 16 MB 重传
修复之一:把回退字体重新生成为 2048 乘 2048 的页面
修复之二:在切换语言之前批量加入字形,而不是在切换过程中现加
结果(经 Unity 博客转述的团队数据):日文新增图集内存从约 48 MB 降到每字体 4-8 MB
修复背后的习惯:先在最弱的硬件上剖析,在真机开发构建上量、改、再量
数字背后的游戏
Foxy Dumplings 是一款温馨烹饪经营游戏,主角 Lisa 是一位职业厨师,在职业倦怠后带着家传饺子配方和一辆餐车重新开始。玩家会走过 12 个取材自真实饮食文化的地点,种食材、学地方菜谱、经营餐车、发明自己的菜品。开发团队是 Soft Crunch Games 的四人核心组,Grzegorz Wątroba 一人负责全部编程、平台移植、构建管线与送审工作。游戏计划登陆 PC(Steam、GOG、Epic Games Store、支持 Xbox Play Anywhere 的微软商店),以及 Nintendo Switch
2、Nintendo Switch、PlayStation
4、PlayStation
5、Xbox Series X 与 S、iOS 和 Android,预计 2027 年发售,使用 Unity 6.3 LTS。
整个项目的铁律是:每个平台拿到的都是同一份提交产出的同一个游戏。没有分支,没有半年后才到的移动版。正是这份纪律让字体故事值得借鉴,因为它也是这份纪律的产物:团队支持 14 种语言,包括中文、日文、韩文和泰文,每种语言各有自己的字体图集。
字体图集是一张存着游戏需要绘制的字形的纹理表。静态图集是提前烘焙好的固定字形集合。回退图集是当前字体没有某个字形时兜底的地方。Unity 的 TextMeshPro 文档用一般性的语言描述了同样的机制:一张字体图集能容纳的字形数量有限,找不到字形时回退系统会去搜索其他字体资源。这套兜底机制本身是正常的、有文档的。在 Foxy Dumplings 里,出问题的是兜底的尺寸。
现象
团队发现切换语言时会出现内存尖峰。这句话值得停一下,因为这是最容易被挥手放过的症状。切换语言是偶尔才做一次的操作,切换时的尖峰很容易被归咎于加载、新语言资源,或者干脆不了了之。团队没有猜,他们剖析了分配路径。
剖析发现了什么
静态图集里缺失的字形会在运行时被光栅化,塞进超大的 4096 乘 4096 回退图集,每个新字形触发一次完整 16 MB 的图集重传。把这个机制慢慢读一遍,因为里面是两种成本相乘。
第一,重传发生在运行时,也就是游玩过程中。静态图集没覆盖的每个字形,一出现在屏幕上就成了现做的活。第二,它落入的回退图集是 4096 乘 4096,而加入一个字形会重传整张图集,不只是新字形。一个新字形,16 MB 上传。再来一个字形,又是 16 MB。成本不跟新字形的大小成正比,而跟它落入的整页大小成正比。
这也解释了为什么尖峰偏偏出现在切换语言时。切换语言正是大量当前图集从未画过的字形突然需要绘制的时刻:新菜单、新对话、新物品名,一次全来,而且用的是上一种语言从未碰过的书写系统。日文字符集大,洪峰也最大,报道的数字正说明了这一点。
数字为什么对得上
Unity 博客给出的重传数字是 4096 乘 4096 图集对应 16 MB。这个数字与单通道图集页面一致:4096 乘 4096 等于 16,777,216 个纹素,按每纹素 1 字节算就是 16 MB。这道算术是我们在核对博客数字,不是博客之外的另一项主张。2048 乘 2048 的页面是 4,194,304 个纹素,按同样的每纹素 1 字节算是约 4 MB。所以修复后每字体 4-8 MB 的结果,大致对应每字体一到两页 2048 页面,而此前日文需要约 48 MB 的新增图集内存。每字体到底需要几页,取决于该字体实际需要的字形数量,这也是博客给的是一个范围而不是一个单值的原因。
两部分修复
第一部分:把回退字体重新生成为 2048 乘 2048 的页面。页面缩小后,每次重传的成本也随之缩小为原来的四分之一,因为重传成本就是整页。每个新字形的 16 MB 代价在其他条件不变的情况下先变成 4 MB。
第二部分:在切换之前批量加入字形。这是最容易被略过的部分,也是真正消除尖峰而不是仅仅缩小尖峰的部分。如果字形在切换过程中才加入,切换本身就要在玩家面前支付光栅化与上传成本,时机最糟。如果提前批量加入,成本就挪到了团队能控制的时刻,切换本身不再产生新的光栅化工作。页面变小让每次上传更便宜,提前批量让切换不再是上传发生的时刻。
报道的结果:日文新增图集内存从约 48 MB 降到每字体 4-8 MB。两个数字都是经 Unity 博客转述的团队数据,不是我们独立实测的。我们核实的是机制说得通、算术对得上,而且修复同时针对了机制的两半:页面尺寸和加入时机。
修复背后的剖析习惯
字体修复不是一位字体专家带着字体答案空降的,而是团队到处都用的剖析习惯的产物。按同一篇博客的描述,Wątroba 的流程是:在真机上做开发构建,接上 Unity Profiler,找到贵的东西,量一遍,修掉,再量一遍。他的原话是:设备才是王。
同样的习惯在同一个项目里还抓到了另一处浪费。厨房的一些效果被渲染进一张 4K 渲染纹理再合成到 UI 上,而在 1080p 或 720p 屏幕上根本没必要。把渲染纹理改成跟随实际屏幕分辨率,并关掉游戏从未用过的 HDR 与深度纹理后,Steam Deck 上那一层每帧填充的像素减少到约原来的八分之一,渲染纹理从约 32 MB 降到约 4 MB,画面上看不出变化。同一个套路,不同的系统:找到分配,检查尺寸是否跟屏幕实际需要匹配,缩小容器,再量一遍。
这也是为什么字体数字值得信任但不值得崇拜。它们是一个团队在一个游戏上的实测结果,经 Unity 博客报道,机制与算术都可核查。它们不是承诺你的游戏能拿到同样的比例。你的字形数量、字体与页面尺寸决定你的比例。
开发者清单
在你发售的最弱设备上剖析语言切换,别只在编辑器里看,而且要看分配路径,不只看总内存
把回退图集页面做小:2048 页面把每次重传封顶在 4096 页面的约四分之一
在切换发生之前预批量加入切换后需要的字形,让切换本身不触发运行时光栅化与整页重传
每种语言各用自己的字体图集,并在本地化设置支持的情况下各用自己的 Addressable 分组,让切换语言时只加载该语言的表
把任何整张纹理重传都当作异味:如果加一个小东西就要重传整页,问题在页,不在东西
修复后在同一设备、同一切换操作上再量一遍,按每字体报范围,不报一个笼统的单值
这个案例没有证明什么
48 MB 到 4-8 MB 的数字是经 Unity 博客转述的团队数据。Foxy Dumplings 尚未发售,我们没有独立实测,也没有拿出自己的新基准。
博客只给了日文数字,没有给出其余 13 种语言的逐语言结果,本文也不估算它们。
博客没有公布这次修复的代码,所以本文也不公布代码,只按博客的描述讲流程。
博客没有说明这些字体的图集渲染模式,所以本文不做断言。16 MB 的算术核对假设单通道页面,因为博客的 16 MB 数字与此一致。
本文引用的 Unity 文档解释的是通用的回退机制,是理解案例的背景,不是文档明确推荐 2048 页面的证据。
来源与证据边界
来源:Adam Axler,《How Soft Crunch Games Built Foxy Dumplings For Every Platform》,Unity 博客,2026 年 10 月 16 日;Unity TextMeshPro 文档《Fallback font assets》;Unity TextMeshPro 文档《Dynamic font assets》;Unity 手册《Introduction to font assets》。本文全部数字均为经 Unity 博客转述的团队数据,或正文中已标注的对这些数字的算术核对。本文没有编造任何新的基准、帧数或实测结果。
一行被重算 63000 次的字符串长度,是怎么让 GTA Online 读盘 6 分钟的
为什么我的网页版游戏只有在玩家不断合成之后才会崩溃?
本文不含任何联盟链接。正文中的全部时间与内存数字均已注明来源;本文没有编造任何新的基准、帧数或实测结果。

