记录一个批量修改场景内字体的工具脚本。
csharp
using System.Linq;
using TMPro;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
public class ChangeFont : EditorWindow
{
private TMP_FontAsset selectedFont;
private string directory = "Please Enter The Full Path";//相对于项目文件夹的路径 Assets/...
//菜单项
[MenuItem("Tools/Change Font")]
private static void ShowWindow()
{
//获取或创建一个ChangeFont实例,并进行显示
EditorWindow.GetWindow<ChangeFont>("Change Font");
}
//绘制编辑器窗口的界面
private void OnGUI()
{
//提示
EditorGUILayout.LabelField("Select Font:", EditorStyles.boldLabel);
//显示一个下拉列表,让用户选择一个字体
selectedFont = (TMP_FontAsset)EditorGUILayout.ObjectField(selectedFont, typeof(TMP_FontAsset), false);
//添加一个按钮,点击按钮时更换所有字体
if (GUILayout.Button("Apply All 3DFonts In Scene"))
{
if (selectedFont != null)
{
ChangeAll3DFonts(selectedFont);
// 获取当前场景的路径
string scenePath = SceneManager.GetActiveScene().path;
// 保存当前场景
EditorSceneManager.SaveScene(SceneManager.GetSceneByPath(scenePath));
Debug.Log("Scene saved: " + scenePath);
}
else
{
Debug.LogWarning("Please select a font first!");
}
}
if (GUILayout.Button("Apply All 2DFonts In Scene"))
{
if (selectedFont != null)
{
ChangeAll2DFonts(selectedFont);
// 获取当前场景的路径
string scenePath = SceneManager.GetActiveScene().path;
// 保存当前场景
EditorSceneManager.SaveScene(SceneManager.GetSceneByPath(scenePath));
Debug.Log("Scene saved: " + scenePath);
}
else
{
Debug.LogWarning("Please select a font first!");
}
}
EditorGUILayout.LabelField("");
if (GUILayout.Button("Apply All Fonts In All Prefabs"))
{
if (selectedFont != null)
{
ChangeFontsInAllPrefabs(selectedFont);
}
else
{
Debug.LogWarning("Please select a font first!");
}
}
EditorGUILayout.LabelField("");
//输入文本框
directory = EditorGUILayout.TextField("Specified Directory", directory);
if (GUILayout.Button("Apply All Fonts In Prefabs In Directory"))
{
if (selectedFont != null)
{
if (directory != null && directory != "Please enter the full path")
{
ChangeFontsInPrefabsInDirectory(selectedFont, directory);
}
else
{
Debug.LogWarning("Please enter a directory!");
}
}
else
{
Debug.LogWarning("Please select a font first!");
}
}
}
/// <summary>
/// 更换场景中所有文本的字体
/// </summary>
/// <param name="font">选择的字体</param>
private static void ChangeAll3DFonts(TMP_FontAsset font)
{
//得到场景中的所有TMP_Text,并更换TMP_Text的字体
TextMeshPro[] allTexts = GameObject.FindObjectsOfType<TextMeshPro>(true);
foreach (TextMeshPro text in allTexts)
{
text.font = font;
}
if (allTexts.Length > 0)
{
//用于刷新AssetDatabase的缓存和数据,使得最新的资源信息和项目状态能够在编辑器中正确显示和更新
AssetDatabase.Refresh();
Debug.Log("Changed all fonts in scene to: " + font.name);
}
else
{
Debug.Log("There are no fonts to change");
}
}
private static void ChangeAll2DFonts(TMP_FontAsset font)
{
//得到场景中的所有TMP_Text,并更换TMP_Text的字体
TextMeshProUGUI[] allTexts = GameObject.FindObjectsOfType<TextMeshProUGUI>(true);
foreach (TextMeshProUGUI text in allTexts)
{
text.font = font;
}
if (allTexts.Length > 0)
{
//用于刷新AssetDatabase的缓存和数据,使得最新的资源信息和项目状态能够在编辑器中正确显示和更新
AssetDatabase.Refresh();
Debug.Log("Changed all fonts in scene to: " + font.name);
}
else
{
Debug.Log("There are no fonts to change");
}
}
/// <summary>
/// 更换所有预制体中的字体
/// </summary>
/// <param name="font">选择的字体</param>
private static void ChangeFontsInAllPrefabs(TMP_FontAsset font)
{
//查找所有预制体,并返回预制体资源的GUID(全局唯一标识符)数组
string[] prefabPaths = AssetDatabase.FindAssets("t:Prefab");
foreach (string prefabPath in prefabPaths)
{
//将资源的GUID(全局唯一标识符)转换为资源在项目中的路径
string path = AssetDatabase.GUIDToAssetPath(prefabPath);
//从指定路径加载资源对象
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
//预制体不为空 并且 预制体 不是 不可变的
if (prefab != null && !PrefabUtility.IsPartOfImmutablePrefab(prefab))
{
//获取预制体中的所有 TextMeshPro 文本组件
TMP_Text[] texts = prefab.GetComponentsInChildren<TMP_Text>(true);
foreach (var text in texts)
{
text.font = font;
}
//保存修改后的预制体
PrefabUtility.SaveAsPrefabAsset(prefab, path);
}
}
if (prefabPaths.Length > 0)
{
AssetDatabase.Refresh();
Debug.Log("Changed all fonts in scene to: " + font.name);
}
else
{
Debug.Log("There are no fonts to change");
}
}
/// <summary>
/// 更换指定目录下的预制体中的字体
/// </summary>
/// <param name="font">选择的字体</param>
/// <param name="directory">指定的目录,Assets/...</param>
private static void ChangeFontsInPrefabsInDirectory(TMP_FontAsset font, string directory)
{
//AssetDatabase.FindAssets查找指定文件夹下的所有预制体路径
//"t:Prefab" :查找条件,表示查找类型为预制体(Prefab)的资源
//new[] { directory } : 指定查找的文件夹路径,如 "Assets/Resources"
//Select : LINQ 方法,用于对查找到的资源进行转换
//AssetDatabase.GUIDToAssetPath将资源的 GUID 转换为实际的资源路径
string[] prefabPaths = AssetDatabase.FindAssets("t:Prefab", new[] { directory }).Select(AssetDatabase.GUIDToAssetPath).ToArray();
foreach (string path in prefabPaths)
{
//从指定路径加载资源对象
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
//预制体不为空 并且 预制体 不是 不可变的
if (prefab != null && !PrefabUtility.IsPartOfImmutablePrefab(prefab))
{
//更换预制体中所有文本组件的字体
TMP_Text[] prefabTexts = prefab.GetComponentsInChildren<TMP_Text>(true);
foreach (var text in prefabTexts)
{
text.font = font;
}
//保存预制体更改
PrefabUtility.SaveAsPrefabAsset(prefab, PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(prefab), out bool success);
if (success)
{
AssetDatabase.Refresh();
Debug.Log($"Saved prefab: {prefab.name}");
}
else
{
Debug.LogWarning($"Failed to save prefab: {prefab.name}");
}
}
}
if (prefabPaths.Length > 0)
{
Debug.Log("Changed all fonts in prefabs in " + directory + " to: " + font.name);
}
else
{
Debug.Log("There are no fonts to change");
}
}
}