背景
因為項目特殊,工作流的順序和以往的項目不同,美術們字體是在中途更換的,但是之前的字體還需要保留一部分,也就是額外添加一種字體
具體需求:字號大於某值的字體替換成'方正',小於某些字體保持不變,這就需要寫個工具去替換了。
前置知識Unity文件、文件引用、Meta詳解
啟動線程線程參考
步驟
- 掃描項目的UI資源目錄,加載Prefab到內存
- 按條件替換資源
- 進行序列化保存
- 因為項目中有會有控制字體的,掃描和項目綁的很緊的組件
核心代碼
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()
,效果也不錯