具体流程:
- 找到工程中使用到的所有字体
- 找到工程和场景中包含Text的所有对象
- 展示要替换的字体名字让用户选择
- 通过用户选择的字体,展示响应的物体对象
- 一键替换
通过AssetDatabase.FindAssets找到工程中包含的所有字体:
private List<string> FindAllFonts()
{
List<string> list = new List<string>();
// 获取所有字体文件
string[] fontGUIDs = AssetDatabase.FindAssets("t:Font");
foreach (string fontGUID in fontGUIDs)
{
string fontPath = AssetDatabase.GUIDToAssetPath(fontGUID);
Font font = AssetDatabase.LoadAssetAtPath<Font>(fontPath);
list.Add(font.name);
}
list.Add("Arial");//默认字体添加进去
return list;
}
通过AssetDatabase.FindAssets找到工程中的所有预制体
private List<GameObject> GetAllPrefabByAssetDatabase(params string[] path)
{
List<GameObject> _prefabList = new List<GameObject>();
string[] _guids = AssetDatabase.FindAssets("t:Prefab", path);
string _prefabPath = "";
GameObject _prefab;
foreach (var _guid in _guids)
{
_prefabPath = AssetDatabase.GUIDToAssetPath(_guid);
_prefab = AssetDatabase.LoadAssetAtPath(_prefabPath, typeof(GameObject)) as GameObject;
_prefabList.Add(_prefab);
}
#if UNITY_2020_1_OR_NEWER
Text[] texts = GameObject.FindObjectsOfType<Text>(true);
foreach (var text in texts)
{
_prefabList.Add(text.gameObject);
}
#else
Scene activeScene = EditorSceneManager.GetActiveScene();
GameObject[] allObjectsInScene = activeScene.GetRootGameObjects();
foreach (var obj in allObjectsInScene)
{
Text[] texts = obj.GetComponentsInChildren<Text>(true);
foreach (var text in texts)
{
_prefabList.Add(text.gameObject);
}
}
#endif
return _prefabList;
}
过滤没有含Text组件的对象
private List<GameObject> FilterNoTextPrefabs()
{
List<GameObject> templist = new List<GameObject>();
Dic_Font_Prefabs.Clear();
foreach (var prefab in prefabs)
{
Text[] texts = prefab.GetComponentsInChildren<Text>(true);
if (texts.Length != 0)
{
foreach (var text in texts)
{
if (text.font != null)
{
if (!Dic_Font_Prefabs.ContainsKey(text.font.name))
{
Dic_Font_Prefabs.Add(text.font.name, new List<GameObject>());//根据Font类型,添加一个Text集合到字典中
}
if (!Dic_Font_Prefabs[text.font.name].Contains(prefab))
{
Dic_Font_Prefabs[text.font.name].Add(prefab);
}
if (!templist.Contains(prefab))
{
templist.Add(prefab);//包含该Text的预制体添加到集合中
}
}
}
}
}
return templist;
}
最后,用户选择完要替换的字体,选择开始替换即可。
TextMeshPro跟Text是一个道理,只需要把代码中响应的Text和Font改为TextMeshProGUI和FontAssets即可。文章来源:https://www.toymoban.com/news/detail-708516.html
最后附上完整代码:文章来源地址https://www.toymoban.com/news/detail-708516.html
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine.UI;
using System.Linq;
using UnityEditor.SceneManagement;
using UnityEngine.SceneManagement;
/// <summary>
/// 查找替换工程场景中Text的Font
/// </summary>
public class ChangePrefabFont : EditorWindow
{
[MenuItem("Tools/替换字体/Text")]//入口
static void GetWindow()//静态函数
{
//创建窗口
ChangePrefabFont window = EditorWindow.GetWindow<ChangePrefabFont>("Text字体替换窗口");//生成一个unity窗口弹窗
window.Show();//展示OnGUI中的界面显示
}
#region 属性
/// <summary>
/// 工程中包含的字体的名字
/// </summary>
List<string> fontsOnAssets = new List<string>();
/// <summary>
/// 对应字体是否需要替换
/// </summary>
List<bool> textPaidFontRelpace = new List<bool>();
/// <summary>
/// 代替要替换的字体的字体
/// </summary>
List<Font> textReplaceFonts = new List<Font>();
/// <summary>
/// 预制体集合
/// </summary>
List<GameObject> prefabs = new List<GameObject>();
/// <summary>
/// 根据字体类型分类的预制体对象
/// </summary>
Dictionary<string, List<GameObject>> Dic_Font_Prefabs = new Dictionary<string, List<GameObject>>();
#endregion
private void OnEnable()
{
InitFont();
}
private void OnGUI()
{
InitPrefabs();
#region 显示替换选项
EditorGUILayout.LabelField("下面是工程中包含的字体,和工程中&场景中的对象使用的字体情况。请选择要替换的字体:");
for (int i = 0; i < fontsOnAssets.Count; i++)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField($"更换[{fontsOnAssets[i]}]字体");
textPaidFontRelpace[i] = EditorGUILayout.Toggle(textPaidFontRelpace[i], GUILayout.Width(position.width));//是否要替换当前字体的复选框
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField($" 预制体数量:{GetGetUseFontPrefabCount(fontsOnAssets[i])}");
if (!textPaidFontRelpace[i])
{
if (Dic_Font_Prefabs.ContainsKey(fontsOnAssets[i]))
{
foreach (var item in Dic_Font_Prefabs[fontsOnAssets[i]])
{
if (prefabs.Contains(item))
{
prefabs.Remove(item);
}
}
}
}
else
{
EditorGUILayout.LabelField($"代替【{fontsOnAssets[i]}】的字体:");
textReplaceFonts[i] = (Font)EditorGUILayout.ObjectField(textReplaceFonts[i], typeof(Font), true);//代替的字体复选框
if (Dic_Font_Prefabs.ContainsKey(fontsOnAssets[i]))
{
foreach (var item in Dic_Font_Prefabs[fontsOnAssets[i]])
{
if (!prefabs.Contains(item))
{
prefabs.Add(item);
}
}
}
}
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.Space();
#endregion
#region 开始替换操作
if (GUILayout.Button("开始替换"))
{
if (textReplaceFonts == null || textReplaceFonts.Count == 0)
{
EditorUtility.DisplayDialog("提示", "没有字体!", "确定");
return;
}
if (prefabs == null || prefabs.Count == 0)
{
EditorUtility.DisplayDialog("提示", "没有需要替换的对象!", "确定");
return;
}
List<GameObject> ReplaceGo = new List<GameObject>();
Dictionary<string, Font> Dic_Font_ReplaceFont = new Dictionary<string, Font>();
for (int i = 0; i < textPaidFontRelpace.Count; i++)
{
if (textPaidFontRelpace[i] == true)
{
if (textReplaceFonts[i] != null)
{
if (Dic_Font_Prefabs.ContainsKey(fontsOnAssets[i]))
{
ReplaceGo.AddRange(Dic_Font_Prefabs[fontsOnAssets[i]]);
Dic_Font_ReplaceFont.Add(fontsOnAssets[i], textReplaceFonts[i]);
}
else
{
EditorUtility.DisplayDialog("提示", $"使用了【{fontsOnAssets[i]}】字体的预制体数量为0!", "确定");
}
}
else
{
EditorUtility.DisplayDialog("提示", $"【{fontsOnAssets[i]}】的替代字体为空!", "确定");
}
}
}
if (ReplaceGo.Count == 0)
{
EditorUtility.DisplayDialog("提示", "没有需要替换的对象!", "确定");
}
else
{
string hintInfo = "";
foreach (var font in Dic_Font_ReplaceFont)
{
hintInfo += $"{font.Key} >> {font.Value.name}\n";
}
if (EditorUtility.DisplayDialog("确认进行下面的替换?", hintInfo, "确定", "取消"))
{
foreach (var font in Dic_Font_ReplaceFont)
{
ReplaceFont(Dic_Font_Prefabs[font.Key], font.Key, font.Value);
}
SaveChangedToAsset(prefabs);
}
}
}
#endregion
#region 预制体列表
InitReorderableList();
if (reorderableList != null && reorderableList.count != 0)
{
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
reorderableList.DoLayoutList();
EditorGUILayout.EndScrollView();
}
else
{
EditorGUILayout.LabelField("提示:没有需要替换字体的预制体");
}
#endregion
}
#region 列表和滚动窗口
ReorderableList reorderableList;//列表显示
Vector2 scrollPos;//滚动窗口需要
private void DrawHeader(Rect rect)
{
EditorGUI.LabelField(rect, "对象列表数量:" + prefabs.Count);
}
private void DrawElement(Rect rect, int index, bool isActive, bool isFocused)
{
rect.height -= 4;
rect.y += 2;
prefabs[index] = (GameObject)EditorGUI.ObjectField(rect, "包含Text的对象", prefabs[index], typeof(GameObject), true);
}
private void AddItem(ReorderableList list)
{
prefabs.Add(null);
}
#endregion
#region 逻辑方法
/// <summary>
/// 字体相关初始化
/// </summary>
private void InitFont()
{
textPaidFontRelpace.Clear();
textReplaceFonts.Clear();
fontsOnAssets = FindAllFonts();
foreach (var item in fontsOnAssets)
{
textPaidFontRelpace.Add(false);
textReplaceFonts.Add(null);
}
}
/// <summary>
/// 预制体相关初始化
/// </summary>
private void InitPrefabs()
{
prefabs = GetAllPrefabByAssetDatabase();
prefabs = FilterNoTextPrefabs();
prefabs.Clear();
foreach (var item in Dic_Font_Prefabs)
{
prefabs.AddRange(item.Value);
}
}
/// <summary>
/// 初始化链表操作对象
/// </summary>
private void InitReorderableList()
{
prefabs = prefabs.Distinct().ToList();
reorderableList = new ReorderableList(prefabs, typeof(GameObject), true, true, true, true);
reorderableList.drawHeaderCallback = DrawHeader;
reorderableList.drawElementCallback = DrawElement;
reorderableList.onAddCallback = AddItem;
}
#endregion
#region 功能方法
#region 查找和过滤
/// <summary>
/// 找到工程和场景中的含有Text组件的对象
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
private List<GameObject> GetAllPrefabByAssetDatabase(params string[] path)
{
List<GameObject> _prefabList = new List<GameObject>();
string[] _guids = AssetDatabase.FindAssets("t:Prefab", path);
string _prefabPath = "";
GameObject _prefab;
foreach (var _guid in _guids)
{
_prefabPath = AssetDatabase.GUIDToAssetPath(_guid);
_prefab = AssetDatabase.LoadAssetAtPath(_prefabPath, typeof(GameObject)) as GameObject;
_prefabList.Add(_prefab);
}
#if UNITY_2020_1_OR_NEWER
Text[] texts = GameObject.FindObjectsOfType<Text>(true);
foreach (var text in texts)
{
_prefabList.Add(text.gameObject);
}
#else
Scene activeScene = EditorSceneManager.GetActiveScene();
GameObject[] allObjectsInScene = activeScene.GetRootGameObjects();
foreach (var obj in allObjectsInScene)
{
Text[] texts = obj.GetComponentsInChildren<Text>(true);
foreach (var text in texts)
{
_prefabList.Add(text.gameObject);
}
}
#endif
return _prefabList;
}
/// <summary>
/// 过滤没有包含Text的预制体
/// 过滤没有包含付费字体的预制体
/// 根据Text类型分类
/// </summary>
/// <param name="gameObjects"></param>
/// <returns></returns>
private List<GameObject> FilterNoTextPrefabs()
{
List<GameObject> templist = new List<GameObject>();
Dic_Font_Prefabs.Clear();
foreach (var prefab in prefabs)
{
Text[] texts = prefab.GetComponentsInChildren<Text>(true);
if (texts.Length != 0)
{
foreach (var text in texts)
{
if (text.font != null)
{
if (!Dic_Font_Prefabs.ContainsKey(text.font.name))
{
Dic_Font_Prefabs.Add(text.font.name, new List<GameObject>());//根据Font类型,添加一个Text集合到字典中
}
if (!Dic_Font_Prefabs[text.font.name].Contains(prefab))
{
Dic_Font_Prefabs[text.font.name].Add(prefab);
}
if (!templist.Contains(prefab))
{
templist.Add(prefab);//包含该Text的预制体添加到集合中
}
}
}
}
}
return templist;
}
/// <summary>
/// 找到工程中的所有字体文件
/// </summary>
/// <returns>返回字体名称列表</returns>
private List<string> FindAllFonts()
{
List<string> list = new List<string>();
// 获取所有字体文件
string[] fontGUIDs = AssetDatabase.FindAssets("t:Font");
foreach (string fontGUID in fontGUIDs)
{
string fontPath = AssetDatabase.GUIDToAssetPath(fontGUID);
Font font = AssetDatabase.LoadAssetAtPath<Font>(fontPath);
list.Add(font.name);
}
list.Add("Arial");//默认字体添加进去
return list;
}
#endregion
#region 替换字体方法
/// <summary>
/// 替换Text的字体
/// </summary>
/// <param name="texts">要替换的Text集合</param>
/// <param name="fontName">要替换的字体的名字</param>
/// <param name="font">用来替换的字体</param>
private void ReplaceFont(List<GameObject> gameObjects, string fontName, Font font)
{
foreach (var go in gameObjects)
{
Text[] texts = go.GetComponentsInChildren<Text>(true);
foreach (var text in texts)
{
if (text.font != null)
{
if (text.font.name == fontName)
{
text.font = font;
}
}
//else
//{
// text.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
//}
}
}
}
/// <summary>
/// 保存更改
/// </summary>
/// <param name="gameObjects"></param>
private void SaveChangedToAsset(List<GameObject> gameObjects)
{
foreach (var gameObject in gameObjects)
{
EditorUtility.SetDirty(gameObject);
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
EditorUtility.DisplayDialog("提示", "替换完毕!", "确定");
}
#endregion
private List<GameObject> GetUseFontPrefabs(string font)
{
if (Dic_Font_Prefabs.ContainsKey(font))
return Dic_Font_Prefabs[font];
else
return null;
}
private int GetGetUseFontPrefabCount(string font)
{
List<GameObject> temp = GetUseFontPrefabs(font);
return temp == null ? 0 : temp.Count;
}
#endregion
}
到了这里,关于一键替换工程文件和场景中的UI对象字体的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!