Шрифты
Есть проблема: TMP не особо дружит с Addressables. TMP предполагает, что шрифты хранятся в ресурсах и сделать их асинхронную загрузку не тривиально. Есть подробный пост в обсуждениях Unity, где расписаны все проблемы.
В этом же посте предлагается ряд решений, в моем случае почти все не сработали, но я расскажу что сработало:
- В билд добавляем только одну пустую сцену, все остальные сцены загружаем через Addressables. В этой пустой сцене не должно быть ссылок на шрифты.
- Шрифты не складываем в Resources, кладём куда-нибудь в другое место, и выносим в отдельный Asset Group, чтобы они не дублировались.
- Разбираемся с TMP Settings. В нем есть ссылка на шрифт по умолчанию. Её нужно удалять на время билда, чтобы шрифт не попал в основной билд. Можно делать это вручную, но я сделал это автоматическим скриптом:
public class TmpSettingsCleaner : IPreprocessBuildWithReport
{
private static TMP_Settings tmpSettings;
private static FieldInfo defaultFontField;
private static object defaultFont;
public int callbackOrder => 0;
public void OnPreprocessBuild(BuildReport report)
{
tmpSettings = Resources.Load<TMP_Settings>("TMP Settings");
defaultFontField = tmpSettings.GetType()
.GetField("m_defaultFontAsset", BindingFlags.Instance | BindingFlags.NonPublic);
defaultFont = defaultFontField!.GetValue(tmpSettings);
Debug.Log($"Default TMP font was {defaultFont}, now it is null");
defaultFontField.SetValue(tmpSettings, null);
}
[PostProcessBuild]
public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
{
defaultFontField.SetValue(tmpSettings, defaultFont);
Debug.Log($"Restored default font {defaultFont}");
}
}Про способы создания атласов:
В TMP есть два варианта создания атласа: статический и динамический. Я считаю, что для веб игр однозначно выигрывает динамический вариант, потому что он сильно уменьшает размер билда. Плюс, если в игре есть лидерборды, то для статического варианта нужно будет сразу добавлять в атлас все возможные символы, так как в именах игроков могут встретиться любые символы. И атлас получается огромный, особенно если шрифт поддерживает несколько языков.
Иконки в тексте (Sprite Asset)
Нам понадобилось добавить иконку ресурса в текст. Сложность в том, что у нас несколько локаций, в каждом будет свой ресурс. То есть <sprite name="gems_icons_3"> в пустыне – это рубин, а в другой локации это может быть мандарин или крышка от кока-колы.
Я реализовал это довольно просто с помощью прокси-ассета.
- Создал пустой SpriteAsset, назвал его Proxy
- В TMP Settings выставил Proxy как defaultSpriteAsset
- Добавил все нужные мне атласы с иконками в свойства локации, которую я подгружаю.
- После загрузки мира, добавляю иконки как fallbackSpriteAssets в Proxy:
var proxy = Resources.Load<TMP_SpriteAsset>("Sprite Assets/Proxy");
proxy.fallbackSpriteAssets.Add(currentWorld.Value.FontSprites.GemsIcons);Таким образом, у меня в конкретной локации будут только иконки из этой локации, подгруженные асинхронно через Addressables. Единственный возможный минус, что не будет работать вставка символов через индекс, типа <sprite=3> , ну и ладно.