Для нашей игры художник сам нарисовал шрифт. Это был гигантский объем работы, но в итоге мы можем перевести игру на кучу языков.
Недавно в аналитике мы заметили вот такие ошибки:
The character with Unicode value \U0001F981 was not found in the [Honeycombgames-bold SDF] font asset or any potential fallbacks. It was replaced by Unicode character \u0020 in text object [Username].
Очевидно, что у кого-то в нике используется символ печеньки 🍪. Мы решили порадовать игрока и добавить поддержку этого символа в наш шрифт. Художник быстренько нарисовал символ и добавил в шрифт. Но вот добавить его в TMP Font оказалось не так просто.
Дело в том, что, видимо в целях оптимизации, в Text Mesh Pro нет возможности вытащить все символы из шрифта - ты должен указать, какие символы тебе нужны. Это хорошо работает в игре со статическим текстом, но из-за лидербордов нам реально нужны все символы, что есть. Соответственно, нужно как-то вытащить список всех символов из шрифта.
До печеньки я пользовался вот этим инструментом, который нашел на форме юнити. Он хорошо работает и решает задачу, но есть одна проблема - Font класс из Unity работает максимум с 2-байтными символами, а для записи печеньки нужно 4 байта -
0x0001F36A (1f36a), соответственно и инструмент этот печеньку не находит.Я стал искать другой вариант вытащить все символы из шрифта, и в итоге в том числе с помощью ChatGPT родился вот такой скрипт. Я запускаю его из под Ubuntu (WSL). Он использует команду
ttfdump из пакета texlive-binaries и далее с помощью awk преобразовывает вывод ttfdump в нужный формат списка диапазонов всех символов, которые есть в шрифте.ttfdump font.ttf | grep 'startCharCode' | awk '
{
split($0, a, "[ ,=]+")
group = a[2]
start = a[6]
end = a[8]
if (NR == 1) {
prev_start = start
prev_end = end
} else {
if (start == prev_end + 1) {
prev_end = end
} else {
if (prev_start == prev_end) {
printf("%X,", prev_start)
} else {
printf("%X-%X,", prev_start, prev_end)
}
prev_start = start
prev_end = end
}
}
}
END {
if (prev_start == prev_end) {
printf("%X\n", prev_start)
} else {
printf("%X-%X\n", prev_start, prev_end)
}
}' | tr 'a-f' 'A-F'
Для нашего шрифта мы получили вот такой результат (заметили в конце 1F36A? это и есть наша печенька):
00,0D,20-7E,A1-161,164-17E,18F,192,1A0-1A1,1AF-1B0,1FA-1FF,218-21D,232-233,259,2C6-2C7,2D8-2DD,37E,384-38A,38C,38E-3A1,3A3-3CE,401-40C,40E-44F,451-45C,45E-45F,490-491,1E80-1E85,1EA0-1EF9,2013-2014,2018-2019,201C-201E,2020-2022,2026,2030,2039-203A,2044,2070,2074-2079,207D-207E,2080-2089,208D-208E,20AB-20AC,20BD,2116,2122,2126,212E,2202,2206,220F,2211-2212,221A,221E,222B,2248,2260,2264-2265,25CA,E000-E008,E184,E300-E309,E310-E319,E320-E321,EFED-EFEE,EFF1-EFF3,EFF5,EFF7,F629-F634,F638-F64C,F64E-F66C,F6AE-F6BD,F6C3,F6C9-F6D8,F6DC,F6DF-F6E8,F730-F739,FB00-FB04,1F36A
Для справки: команда ttfdump в моём случае выводит информацию о группах вот в таком формате:
Group 0 : startCharCode = 0, endCharCode = 0, startGlyphID = 1
Group 1 : startCharCode = 13, endCharCode = 13, startGlyphID = 2
Group 2 : startCharCode = 32, endCharCode = 34, startGlyphID = 3
Group 3 : startCharCode = 35, endCharCode = 35, startGlyphID = 216
P. S. В этом посте я использую слово "символ" вместо "глиф", хотя, конечно, "глиф" это правильное слово.
#тайные_знания