背景
因为项目特殊,工作流的顺序和以往的项目不同,美术们字体是在中途更换的,但是之前的字体还需要保留一部分,也就是额外添加一种字体
具体需求:字号大于某值的字体替换成'方正',小于某些字体保持不变,这就需要写个工具去替换了。
前置知识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()
,效果也不错