在使用 Unity 开发的游戏中,避免使用 Resources 文件夹,而使用 AssetBundle 打包,但是 TextMesh Pro 组件自带了 Resources 文件夹,此时 AssetBundle 资源如果引用了它,那么就会把 TextMesh Pro 打成 AssetBundle,造成冗余。但是如果仅把 TextMesh Pro 的 Resources 文件夹改名掉,就会造成【TMP_Settings】读取失败,字体完全无法显示。
【TMP_Settings】类是个单例,在初始使用的时候,会去 Resources 文件夹读取资源配置,反射看代码如下:
public static TMP_Settings instance
{
get
{
if ((UnityEngine.Object) TMP_Settings.s_Instance == (UnityEngine.Object) null)
TMP_Settings.s_Instance = UnityEngine.Resources.Load<TMP_Settings>("TMP Settings");
return TMP_Settings.s_Instance;
}
}
也没有接口可以用来赋值TMP_Settings.s_Instance
,所以造成后面读取默认字体等失败。
既然没有接口可以直接赋值,那么就损失点性能使用反射来对其进行赋值,因为只需赋值一次,所以性能可以忽略。将 Resources 文件夹改名成其他名称,然后把TMP_Settings.asset
文件移到 AssetBundle 预制读取目录。最后在游戏资源检测完毕后,调用如下代码:
public class TMPHelper
{
public static void LoadSettings()
{
TMP_Settings settings = ResManager.LoadAsset<TMP_Settings>("Prefab/Configs/TMPPro/TMP_Settings.asset");
var settingsType = settings.GetType();
var settingsInstanceInfo = settingsType.GetField("s_Instance", BindingFlags.Static | BindingFlags.NonPublic);
settingsInstanceInfo.SetValue(null, settings);
}
}
这样子游戏运行起来就会自动赋值TMP_Settings.s_Instance
,但是在编辑器下就无法使用 TextMesh Pro 组件,所以也需要在编辑器下对其进行赋值,添加编辑器类,代码如下:
[InitializeOnLoad]
public class GameLauncher
{
static GameLauncher()
{
LoadSettings();
}
public static void LoadSettings()
{
TMP_Settings settings = ResManagerEditor.LoadAssetEditor<TMP_Settings>("Prefab/Configs/TMPPro/TMP_Settings.asset");
var settingsType = settings.GetType();
var settingsInstanceInfo = settingsType.GetField("s_Instance", BindingFlags.Static | BindingFlags.NonPublic);
settingsInstanceInfo.SetValue(null, settings);
}
}
这样,只要编辑器一打开就会自动调用赋值。
更改了 Resources 文件夹,会导致文本解析标签失败,即无法内嵌子字体,无法使用如下语法:
Would you like a different font?font> or just a different material?
因为内部解析的时候,会去 Resources 文件夹下的 Fonts & Materials 文件夹寻找字体,寻找不到所以就显示失败。综合考虑不使用这种写法。