Unity开发微信小游戏-生僻字的处理
2026/03
09
19:03
Unity使用GB2312字体,在App中生僻字会Fallback到系统字体,但是在微信小游戏中直接无法显示
处理方案为,使用fontforge自动化导入其它替代字体中的字形到已有字体中进行补充
1、安装 fontforge
fontforge支持python脚本自动化运行;
2、添加替换脚本replace.py
import fontforge
import os
import tempfile
def get_glyph_by_unicode(font, unicode_code):
try:
if unicode_code in font:
return font[unicode_code]
glyph_name = f"uni{hex(unicode_code)[2:].upper()}"
if glyph_name in font:
return font[glyph_name]
glyph_name_u = f"u{hex(unicode_code)[2:]}"
if glyph_name_u in font:
return font[glyph_name_u]
return None
except:
return None
def replace_single_glyph(source_font, target_font, unicode_code, glyph_alias=None):
glyph_alias = glyph_alias or f"U+{hex(unicode_code)[2:].upper()}"
source_glyph = get_glyph_by_unicode(source_font, unicode_code)
if not source_glyph:
print(f"警告:源字体中未找到字形 {glyph_alias}(Unicode:{unicode_code}),跳过")
return False
target_glyph = get_glyph_by_unicode(target_font, unicode_code)
if target_glyph:
print(f"提示:{glyph_alias} 存在..")
return True
target_font.createChar(int(unicode_code), f"uni{hex(unicode_code)[2:].upper()}")
target_glyph = get_glyph_by_unicode(target_font, unicode_code)
if not target_glyph:
print(f"错误:无法创建字形 {glyph_alias},跳过")
return False
try:
source_font.selection.select(int(unicode_code))
source_font.copy()
target_font.selection.select(int(unicode_code))
target_font.paste()
target_glyph.width = int(round(source_glyph.width))
if hasattr(source_glyph, 'lsb'):
target_glyph.lsb = int(round(source_glyph.lsb))
target_glyph.rsb = int(round(source_glyph.rsb))
elif hasattr(source_glyph, 'left_side_bearing'):
target_glyph.left_side_bearing = int(round(source_glyph.left_side_bearing))
target_glyph.right_side_bearing = int(round(source_glyph.right_side_bearing))
print(f"成功替换字形 {glyph_alias}(Unicode:{unicode_code})")
return True
except Exception as e:
print(f"错误:替换字形 {glyph_alias} 失败 - {str(e)}")
return False
def replace_glyphs(source_font_path, target_font_path, output_font_path, glyph_unicode_map):
temp_font = tempfile.mktemp(suffix=".sfd")
try:
source_font = fontforge.open(source_font_path)
target_font = fontforge.open(target_font_path)
source_em = int(round(source_font.em))
target_font.em = source_em
for glyph_alias, unicode_code in glyph_unicode_map.items():
replace_single_glyph(source_font, target_font, unicode_code, glyph_alias)
target_font.generate(output_font_path)
print(f"\n字体替换完成!新字体路径:{output_font_path}")
except Exception as e:
print(f"\n执行出错:{str(e)}")
import traceback
traceback.print_exc()
finally:
if 'source_font' in locals():
source_font.close()
if 'target_font' in locals():
target_font.close()
if os.path.exists(temp_font):
try:
os.remove(temp_font)
except:
pass
if __name__ == "__main__":
SOURCE_FONT = "gbk.ttf"
TARGET_FONT = "gb2312.ttf"
OUTPUT_FONT = "out.TTF"
GLYPH_UNICODE_MAP = {
"睺": 30586,
"啰": 21872,
"妺": 22970,
"嶽": 23997,
"猨": 29480,
"臜": 33244,
"雘": 38616,
}
replace_glyphs(SOURCE_FONT, TARGET_FONT, OUTPUT_FONT, GLYPH_UNICODE_MAP)
3、书写一个工具全局扫描所有的生僻字
internal class Program
{
static void Main(string[] args)
{
try
{
string filePath = "language.txt";
if (!File.Exists(filePath))
{
Console.WriteLine($"文件 {filePath} 不存在!");
return;
}
string[] lines = File.ReadAllLines(filePath);
HashSet<char> allChars = new HashSet<char>();
ExtractChineseCharacters(lines, allChars);
SaveResults(allChars);
}
catch (Exception ex)
{
Console.WriteLine($"发生错误: {ex.Message}");
}
}
static void ExtractChineseCharacters(string[] lines, HashSet<char> chars)
{
foreach (string line in lines)
{
foreach (char c in line)
{
if (c < 10000) // 小于10000的字符通常不是汉字,直接跳过
{
continue;
}
if (chars.Contains(c))
{
continue;
}
if (IsGB2312(c))
{
continue;
}
chars.Add(c);
}
}
}
private static Encoding gb2312 = Encoding.GetEncoding("gb2312");
private static char[] charBuff = new char[1];
public static bool IsGB2312(char c)
{
try
{
charBuff[0] = c;
byte[] bytes = gb2312.GetBytes(charBuff);
if (bytes.Length == 2)
{
if (bytes[0] >= 0xA1 && bytes[0] <= 0xFE && bytes[1] >= 0xA1 && bytes[1] <= 0xFE)
{
return true;
}
}
return false;
}
catch
{
return false;
}
}
static void SaveResults(HashSet<char> allChars)
{
using (StreamWriter writer = new StreamWriter("GBK.txt"))
{
foreach (char c in allChars)
{
writer.WriteLine($"\"{c}\": {(int)c},");
}
}
}
}
将输出的生僻字贴到python脚本中,运行
fontforge.exe -script replace.py
即可获得补全的字体文件out.ttf
CopyRights: The Post by BY-NC-SA For Authorization,Original If Not Noted,Reprint Please Indicate From 老刘@开发笔记
Post Link: Unity开发微信小游戏-生僻字的处理
Post Link: Unity开发微信小游戏-生僻字的处理