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