unity 批量修改场景内字体工具

记录一个批量修改场景内字体的工具脚本。

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");
        }
    }
}
相关推荐
ellis197019 小时前
Unity中ScriptableObject用法整理
unity
玉梅小洋1 天前
Unity Muse 完整使用文档:Sprite+Texture专项
unity·ai·游戏引擎
能源革命1 天前
Three.js、Unity、Cesium对比分析
开发语言·javascript·unity
timathy332 天前
Unity Addressable 实现Build时自定义剔除资源组
unity·游戏引擎
一种时光3 天前
Unity 获取当前播放的动画,判断是否是某个动画
unity·游戏引擎
不绝1913 天前
Unity入门 :场景叠加/预制体资源包/脚本资源/生命周期函数/Inspector页面
unity·游戏引擎
在路上看风景3 天前
20. 资源和脚本的绑定关系
unity
yj爆裂鼓手3 天前
unity对象池
unity·c#
在路上看风景3 天前
3.7 SRP Batcher
unity