如何在运行时加载特定平台的字体

3
我正在尝试使应用根据平台设置一些资产。
第一步是根据操作系统选择字体,Android使用Roboto,iOS使用SanFrancisco。
简单地说,Unity无法在运行时导入字体,这与其他跨平台IDE相比是一个相当大的缺点,但我们不在这里评判。另一个解决方案是使用AssetBundle,但由于无法解释的原因,它对我来说无法工作...
此外,将基本资产(如字体)存储为除字体以外的其他内容并不被广泛接受。
因此,我的最终解决方案是这个丑陋的脚本:
class FontFamily
{
     [Header("Android")]
     [SerializeField]
     private Font regularAndroid = null;
     [SerializeField]
     private Font boldAndroid = null;
     [SerializeField]
     private Font italicAndroid = null;
     [Header("iOS")]
     [SerializeField]
     private Font regularIOS = null;
     [SerializeField]
     private Font boldIOS = null;
     [SerializeField]
     private Font italicIOS = null;
     public Font Regular
     {
         get
         {
 #if UNITY_ANDROID
             return this.regularAndroid;
 #elif UNITY_IOS
             return this.regularIOS;
 #endif
         }
     }
     public Font Bold
     {
         get
         {
 #if UNITY_ANDROID
             return this.boldAndroid;
 #elif UNITY_IOS
             return this.boldIOS;
 #endif
         }
     }
     public Font Italic
     {
         get
         {
 #if UNITY_ANDROID
             return this.italicAndroid;
 #elif UNITY_IOS
             return this.italicIOS;
 #endif
         }
     }
 }

我只是想找到一种改进的方法,因为长期来看这不是一个可行的解决方案。当我切换时,我甚至不能将宏置于参考资料中,因为它们会丢失。我考虑使用一些预先构建的脚本,你怎么做呢?

另一个解决方案是使用AssetBundle,但由于无法解释的原因,它对我来说无法正常工作... 那Resources文件夹呢? - Programmer
这样做会违背不加载无用资源的初衷。整个目的是为了在Android版本中仅包含Android资产,在iOS版本中也是如此。资源将构建整个内容。 - Everts
我本希望能够从URL下载ttf文件,但是Unity不支持运行时加载字体...这就是我尝试使用AB的原因,但它并没有起作用。我期待一种不需要依赖于Unity的方法。 - Everts
1
非常有趣的问题,我认为有更好的解决方案。当我回到我的工作电脑时,我会深入挖掘这个问题。 - Programmer
Unity论坛上一位曾经是Unity员工的老用户提供了一个解决方案,即使用AB。这似乎是可行的(如果我能让它起作用),但肯定有更多适用于Xamarin或Web设计中广泛使用的跨平台概念的解决方案。我希望看到Unity能够更本地化地开发UI,以便非游戏应用程序也能受益。 - Everts
1个回答

6

实际上,Unity可以在运行时导入字体,而无需使用ABs,但只能使用操作系统的字体,方法是使用Font.CreateDynamicFontFromOSFont

以下是加载Android中的Roboto字体和iOS中的San Francisco字体的简单脚本:

using UnityEngine;

public class LoadFontFromOS : MonoBehaviour {

    const string ANDROID_FONT_NAME = "Roboto";
    const string IOS_FONT_NAME = "SanFrancisco";

    string[] OSFonts;
    static Font selectedFont;
    public static Font SelectedFont {
        get {
            return selectedFont;
        }
    }
    static bool isFontFound;
    public static bool IsFontFound {
        get {
            return isFontFound;
        }
    }

    private void Awake() {
        isFontFound = false;
        OSFonts = Font.GetOSInstalledFontNames();
        foreach (var font in OSFonts) {
#if UNITY_ANDROID
            if (font == ANDROID_FONT_NAME) {
                selectedFont = Font.CreateDynamicFontFromOSFont(ANDROID_FONT_NAME, 1);
                isFontFound = true;
            }
#elif UNITY_IOS
            if (font == IOS_FONT_NAME) {
                selectedFont = Font.CreateDynamicFontFromOSFont(IOS_FONT_NAME, 1);
                isFontFound = true;
            }
#endif
        }
    }
}

您可以通过简单的方法更改所有文本类型的字体。

text.font = LoadFontFromOS.IsFontFound ? LoadFontFromOS.SelectedFont : text.font;

需要时进行操作。

我在安卓上测试过了,它可以正常工作。我没有iOS设备来测试,但应该也可以正常工作。


我已将“size”参数更改为1,但显然在变化值时没有任何变化(使用1和10000进行测试,字体大小相同)。我不知道为什么会发生这种情况。 - Galandil
1
你的脚本在 IOS 指令下有一个小错别字;Font.CreateDynamicFontFromOSFont(ANDROID_FONT_NAME, 1); 应该改为 Font.CreateDynamicFontFromOSFont(IOS_FONT_NAME, 1); :) - Lece
1
不幸的是,这对我来说似乎无法工作(Unity 2019.1.0f2,iOS 12.2)。脚本本身运行良好,但是“SanFrancisco”或任何其他变体,例如“San Francisco”或“SF”,都不在从Font.GetOSInstalledFontNames()返回的字体名称列表中。有没有人在iOS上使用San Francisco使其正常工作? - Paul Straw
我可以确认这在Android上运行良好。但是,正如@PaulStraw所提到的那样,iOS列表中没有旧金山字体。 - railon
@PaulStraw @railon 或许有点晚了,但字体路径和字体文件名分别为/System/Library/Fonts/CoreUI/SFUI.ttfSystem Font - Kerem Baydoğan
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接