成果:优化前2.5M的字体文件优化后只有几百kb不到1m了
背景:unity微信小游戏要求字体文件在3m以内姑且我认为2.5m以内实际可以干到1M以内。微信小游戏要求尽可能的进游戏快,在这个背景下我们需要对字体进行优化,我采用的是3500字的常见中文,一些符号它没有包含进去所以用了一个FallbackLIst字体库(很小)另外参考博客优化TMP字体资源大小的思路_tmp优化-CSDN博客 另外我多提一下首包界面的字体也需要单独处理buildin的字体没法显示中文只能显示数字这是一个坑(webgl平台),所以也需要进行字体裁剪,可以百度fontzip64链接在这里FontZip/FontZip at master · forJrking/FontZip · GitHub
进去后下载FontZip64.exe
运行后长这样如下图所示:首先选中你的字体然后输入提取字,提取字你可以写一个工具去提取工程中的所有中文文本,或者自定义。
进去后下载
第一步,将FontAsset的模式改为静态
上图中字体是静态还是动态也可以通过代码设置接口如下:
TMP_Settings.GetFontAsset().atlasPopulationMode = AtlasPopulationMode.Static;
TMP_Settings.GetFontAsset().atlasPopulationMode = AtlasPopulationMode.Dynamic;
第二部选中编辑器中的otf字体如下图所示,选中这张贴图资源复制一份出来。复制出来后长这样:
第三步:选中字体如下图所示
第四步:注意这里的EnglishAltas纯纹理格式Texture2D转为png格式
这里我们可以先把原来字体内置的纹理给删除直接上代码就是
先选中字体然后执行下面的这个菜单项
[MenuItem("Tools/优化字体/第一步")]
static void OplizeFont()
{
if (Selection.activeObject is TMP_FontAsset TMPFontAsset)
{
AssetDatabase.RemoveObjectFromAsset(TMPFontAsset.atlasTexture);
AssetDatabase.SaveAssets();
}
else
{
Debug.Log("请选中字体文件");
}
}
然后选中新的字体纹理执行菜单 这里按之前优化TMP字体资源大小的思路_tmp优化-CSDN博客
他这里提到的方法我试了一下有报错,我这里改了一下。我们提取出来的纹理文件没有开启可读属性所以这里需要读取他的纹理像素,需要用到RT的技术
[MenuItem("Tools/优化字体/第二步")]
static void OplizeFont2()
{
if (Selection.activeObject is Texture2D readOnlyTexture)//选中上面提到的新字体纹理
{
Texture2D newTex = new Texture2D(readOnlyTexture.width, readOnlyTexture.height, readOnlyTexture.format, false);
// 读取原始纹理的像素数据
RenderTexture currentRT = RenderTexture.active;
RenderTexture tempRT = RenderTexture.GetTemporary(readOnlyTexture.width, readOnlyTexture.height, 0, RenderTextureFormat.ARGB32);
Graphics.Blit(readOnlyTexture, tempRT); // readOnlyTexture选中的纹理渲染到tempRT上
RenderTexture.active = tempRT;//设置为激活 RT 然后就可以读取像素 ReadPixels
newTex.ReadPixels(new Rect(0, 0, readOnlyTexture.width, readOnlyTexture.height), 0, 0);
newTex.Apply();
// 现在 newTex 包含了纹理的数据
byte[] pngData = newTex.EncodeToPNG();
// 指定保存文件的路径
byte[] bytes = pngData;
System.IO.File.WriteAllBytes("Assets/Res_Dev/Fonts/English SDF.png", bytes);
AssetDatabase.Refresh();
var TextPng = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/Res_Dev/Fonts/English SDF.png");
//批量赋值,或者只用上面的代码创建png,手动赋值
//加载字体
TMP_FontAsset targeFontAsset = AssetDatabase.LoadAssetAtPath<TMP_FontAsset>("Assets/Res_Dev/Fonts/English SDF.asset");
var matPresets = TMP_EditorUtility.FindMaterialReferences(targeFontAsset);
foreach (var material in matPresets)
{
material.SetTexture("_MainTex", TextPng);//设置字体材质贴图
}
AssetDatabase.Refresh(); // 更新到unity本地数据库library
// 重新设置 RenderTexture
RenderTexture.active = currentRT;// 还原成原currentRT
RenderTexture.ReleaseTemporary(tempRT);// 释放new的RT资源
}
}