Unity项目中批量替换字体


背景

因为项目特殊,工作流的顺序和以往的项目不同,美术们字体是在中途更换的,但是之前的字体还需要保留一部分,也就是额外添加一种字体

具体需求:字号大于某值的字体替换成'方正',小于某些字体保持不变,这就需要写个工具去替换了。

前置知识Unity文件、文件引用、Meta详解
启动线程线程参考

步骤

  1. 扫描项目的UI资源目录,加载Prefab到内存
  2. 按条件替换资源
  3. 进行序列化保存
  4. 因为项目中有会有控制字体的,扫描和项目绑的很紧的组件

核心代码

private bool ReplaceTMPUGUIFont(string path, GameObject prefab, Dictionary<int, bool> ignoreHashList)
{
    bool isModify = false;
    TextMeshProUGUI[] coms = prefab.GetComponentsInChildren<TextMeshProUGUI>(true);
    foreach (TextMeshProUGUI com in coms)
    {
        string curFontGuid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(com.font));
        if ((!ignoreHashList.ContainsKey(com.GetHashCode())) && (m_OldFontGuid == curFontGuid) && (com.fontSize >= this.fontSize))
        {
            try
            {
                Debug.Assert(com.fontMaterial != null);
            }
            catch (Exception e)
            {
                isModify = true;
                com.font = newFontAsset;
                com.fontMaterial = newFontAsset.material;
                Debug.LogWarning(string.Format("{0}:{1}:节点字体无材质信息,已设置成默认材质,请检查正确性", path, com.transform.name));
                continue;
            }
            string matName = com.fontMaterial.name.Remove(0, com.font.name.Length).Replace(" (Instance)", "");

            string curFontMatPath = fontAssetPath + "/" + com.font.name + matName + ".mat";
            string curFontMatGuid = AssetDatabase.AssetPathToGUID(curFontMatPath);

            string newFontMatPath = fontAssetPath + "/" + newFontAsset.name + matName + ".mat";
            string newFontMatGuid = AssetDatabase.AssetPathToGUID(newFontMatPath);

            Material newMat = null;
            bool isDefault = false;
            if (m_MatCache.ContainsKey(curFontMatGuid))
            {
                newMat = m_MatCache[curFontMatGuid];
            }
            else
            {
                if (!File.Exists(m_ProjectPath + newFontMatPath))//如果目标材质资源不存在,创建材质
                {
                    if (File.Exists(m_ProjectPath + curFontMatPath))//如果当前源材质存在
                    {
                        if (!AssetDatabase.CopyAsset(curFontMatPath, newFontMatPath))//进行拷贝资源
                        {
                            Debug.LogError(string.Format("{0}:{1}:节点处理异常,请重试", path, curFontMatPath));
                            continue;
                        }
                    }
                    else//如果当前字体材质不存在
                    {
                        if (com.fontMaterial.name.Replace(" (Instance)", "") == oldFontAsset.material.name)//如果是字体默认资源
                        {
                            isDefault = true;
                        }
                        else
                        {
                            Debug.LogError(string.Format("{0}:资源未找到,请检查材质是否在{1}路径", curFontMatPath, fontAssetPath));
                            continue;
                        }
                    }

                }
                if (isDefault)
                {
                    newMat = newFontAsset.material;
                }
                else
                {
                    newMat = (Material)AssetDatabase.LoadAssetAtPath(newFontMatPath, typeof(Material));
                    newMat.SetTexture(ShaderUtilities.ID_MainTex, newFontAsset.material.GetTexture(ShaderUtilities.ID_MainTex));
                }
                m_MatCache[curFontMatGuid] = newMat;
            }
            isModify = true;
            com.font = newFontAsset;
            com.fontMaterial = newMat;
        }
    }
    return isModify;
}

PS:因为加载资源很慢,然后想在线程加载,写一个进度显示,可惜AssetDatabase.LoadAssetAtPath和其他关于资源控制的函数,都只能在主线程执行,所以使用了EditorUtility.DisplayProgressBar(),效果也不错


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM