站点图标 Wankko Ree's Blog

游戏汉化的那些事——字体篇

开题

众所周知,大部分游戏在打包的时候,会把字体里面明显用不到的字符集删去(比如说中文),也可能用的字体压根就没有中文字符集,所以在做汉化的时候,经常碰到中文显示XXXX的情况。

而出于对还原度的考虑,我对于汉化的字体有以下几点考量:

  1. 样式尽量与原字体一致,如是否衬线、笔画粗细、字符宽高比、运笔风格等
  2. 对于原字体有的字符集,尽量从原字体中迁移,而不是全部采用新字体
  3. 全半角标点除字宽外尽量一致,所以全角标点最好从原字体的半角标点中迁移,并保留中文字宽
  4. 原字体尽量找未精简版本,因为游戏内打包的大概率是精简版的
  5. 原字体可能有自定义字符区,可能会在游戏内使用,所以也得迁移过来

所以,FontCreater无疑是字体合并的神器了。

本篇博客以游戏《史丹利的寓言:终极豪华版》(The Stanley Parable: Ultra Deluxe)为例,记录了Unity游戏汉化过程中从缝合字体到打包SDF的完整经过。

开始捞字体

首先找到一个和原字体风格尽量一致的中文字体,因为游戏中使用的字体比较多,这里以比较有特色的字体LeagueGothic-Regular为例。

先是大海捞针找到一个符合要求的中文字体,这里选择了方正俊仪体-Bold,至于为啥要Bold版本呢?因为这个版本的笔刷粗细正好和原字体非常接近。

开始缝合

先去Google Fonts下载原字体的未精简版本,也就是官方原版,然后用FontCreater打开Google版和中文版两个字体。

将两个字体都按Unicode 字码点排序,方便后续比对。

两边基本拉丁字母区都是95/95满的,那就直接从原字体全选复制过来。

中文字体这边拉丁字母补充-1没满,但是谷歌版这边是满的,那就直接复合一下中文字体的这个字符区(复合完了记得再次排序,因为复合是添加到本区的尾部,但是已有的字符和新添加的可能顺序是交叉的)。

Google版的还有俩非标准字符,不确定游戏版的字体有没有,先别管。

也是从原字体复制过来就完成了这个字符区。

再看拉丁字母扩展-A区的,两边都没满,不过原字体超过半数了,那就两边都复合一下再排个序,然后全选复制过来,再把空的删掉就行。

拉丁字母扩展-B区的两边都没咋满,所以直接记一下原字体的字符分布然后在新字体这边添加就行(当然添加完还是记得排序)。

不过新字体多了个ngrave字符,原字体里没有,直接删掉,然后其他的字符也复制过来就行。

然后新字体还有个国际音标扩展区,这个反正不是中文里用的,删掉就完事。

剩下的几个区也和上面逻辑一样,该补的补,该替换的替换,该删的删。

最后剩下全角与半角的迁移,方法是先从原字体复制,然后在粘贴的时候选择特殊粘贴,只保留轮廓,就可以保留新字体的全角字宽(可以多选复制和粘贴)。

当然,这样子复制过来的字形,默认是居左的,所以咱们需要让其居中(感觉大部分全角标点都是居中吧),不过这一步留到最后做,不然现在居中了待会从游戏版迁移完后还得重新搞。

咱们现在已经完成了从谷歌版到中文字体的迁移,然后再从游戏版字体往中文字体迁移一次,因为游戏版可能对字形有改动,这里不多说了,方法和上面一样,主要就是覆盖字形。

值得注意的是游戏版字体有一些非标准字符,最好也复制过来,方法是点添加字符看哪个非标准是绿的,就在新字体那边添加上。

然后回来去全角区搞居中,双击字形,Ctrl+A全选轮廓,Shift+→几次把定位点大致对准中线(这边中线是500),然后Ctrl+滚轮放大到究极大,几次再次大致对准中线,最后Ctrl+→彻底对准。

最后将新字体的字体属性全部按游戏版字体的字体属性填写即可。

最后的最后,可以尝试导出字体。

发现中文字符间距有点大,于是用自动度量去改改。

改之前先记一下哪些字符区是全角并且需要改间距的。

为了所有中文字符统一间距,咱们这边选固定字宽

选择刚才记下的那些区域后,Finish即可。(不太好选)

最终效果如下:

开始打包

打开Unity,创建一个空项目,打开Package Manager

添加Asset Bundle BrowserTextMeshPro

把字体文件拉到Assets区。

TextMeshProFont Asset Creator创建SDF字体文件。

项目首次使用这个功能会弹出Import,把两个都导入就行。

如下两个按钮都灰了就导入完了,直接关掉。

看一下字符集的范围设定选项,有这么多可以选。

一般是Unicode Range (Hex)就够用,但是这玩意的文本框有最大长度现在,如果精细到每个字符的话,其实是不太够的...所以咱选择Characters from File,然后去写代码打个字符集出来。

from fontTools.ttLib import TTFont

def main():
    otf = TTFont("font/LeagueGothic-Regular/LeagueGothicWithFZJunYT-B-Regular.otf")
    keys = otf.getBestCmap().keys()
    with open("font/LeagueGothic-Regular/set.txt", 'w', encoding="UTF-8") as f:
        for i in keys:
            f.write(chr(i))

if __name__ == '__main__':
    main()

把字符集文件拖到Assets里。

然后选择这个文件。

其他配置选项的话,测试的时候,Packing Method建议用Fast,最终打包时用OptimumSamping Point SizeAtlas Resolution根据字符集数量调整,参数越大打出来的包越大,但是清晰度也越高,不过前者过大或者后者过小会造成一张图里塞不下所有字符集,所以需要多测试几次找到最合适的参数。

比如说咱们这回就没打成功,字符集数量太多了,只塞下5k+就放不下了,所以需要改改参数。

最终在字体大小是94的时候刚好塞下,把打出来的字体包先Save一下去游戏里看看实际情况,如果效果比较好的话就可以打Optimum版本的了。

开始ab打包,打开AssetBundle Browser

先把字体源文件拖进来(顺序不要搞错)。

再把SDF文件拖到右侧,使两者在同一个包内。

切到Build选项卡,参数按自己需求改改就可以Build了。

最终得到:

替换到游戏里去看看(怎么替换不是本篇博客要讲的内容,不做讨论),感觉效果挺好的。

所以最后就是去打包个Optimum版本就大功告成了(巨慢)。


The End
退出移动版