Text预设转TextMeshPro

接到个需求,将项目所有的预设Text改成TextMeshPro

拆分一下:
1.将预设的Text修改为TextMeshPro,并写入主要属性
2.将脚本中的Text 相关代码置换为TextMeshProUGUI
3.重新挂载脚本丢失的引用(如果你用的获取节点方式是代码里写Transform.Find ,而不是拖动到Inspector上,这一步就可以省略啦)

1-2.替换预设中的组件Text,替换脚本中的Text

1.首先写一个方法,替换TextTextMeshProUGUI

	private static void ChangeText2TMP(Text text)
    {
    //缓存text的参数信息
        Transform target = text.transform;
        Vector2 size = text.rectTransform.sizeDelta;
        string strContent = text.text;
        Color color = text.color;
        int fontSize = text.fontSize;
        FontStyle fontStyle = text.fontStyle;
        TextAnchor textAnchor = text.alignment;
        bool richText = text.supportRichText;
        HorizontalWrapMode horizontalWrapMode = text.horizontalOverflow;
        VerticalWrapMode verticalWrapMode = text.verticalOverflow;
        bool raycastTarget = text.raycastTarget;
        //移除text
        GameObject.DestroyImmediate(text);
		
		//添加TextMeshProUGUI,并写入缓存的信息
        TextMeshProUGUI textMeshPro = target.gameObject.AddComponent<TextMeshProUGUI>();
        textMeshPro.rectTransform.sizeDelta = size;
        textMeshPro.text = strContent;
        textMeshPro.color = color;
        textMeshPro.fontSize = fontSize;
        textMeshPro.fontStyle = fontStyle == FontStyle.BoldAndItalic ? FontStyles.Bold : (FontStyles)fontStyle;
        switch (textAnchor)
        {
            case TextAnchor.UpperLeft:
                textMeshPro.alignment = TextAlignmentOptions.TopLeft;
                break;
            case TextAnchor.UpperCenter:
                textMeshPro.alignment = TextAlignmentOptions.Top;
                break;
            case TextAnchor.UpperRight:
                textMeshPro.alignment = TextAlignmentOptions.TopRight;
                break;
            case TextAnchor.MiddleLeft:
                textMeshPro.alignment = TextAlignmentOptions.MidlineLeft;
                break;
            case TextAnchor.MiddleCenter:
                textMeshPro.alignment = TextAlignmentOptions.Midline;
                break;
            case TextAnchor.MiddleRight:
                textMeshPro.alignment = TextAlignmentOptions.MidlineRight;
                break;
            case TextAnchor.LowerLeft:
                textMeshPro.alignment = TextAlignmentOptions.BottomLeft;
                break;
            case TextAnchor.LowerCenter:
                textMeshPro.alignment = TextAlignmentOptions.Bottom;
                break;
            case TextAnchor.LowerRight:
                textMeshPro.alignment = TextAlignmentOptions.BottomRight;
                break;
        }

        textMeshPro.richText = richText;
        if (verticalWrapMode == VerticalWrapMode.Overflow)
        {
            textMeshPro.enableWordWrapping = true;
            textMeshPro.overflowMode = TextOverflowModes.Overflow;
        }
        else
        {
            textMeshPro.enableWordWrapping = horizontalWrapMode == HorizontalWrapMode.Overflow ? false : true;
        }

        textMeshPro.raycastTarget = raycastTarget;
        //这里替换为你需要的TMP字体包路径
        var font = AssetDatabase.LoadAssetAtPath<TMP_FontAsset>("Assets/Art/Font/SourceHanSansCN-Medium SDF.asset");
        textMeshPro.font = font;
    }

2.处理预设,由于修改脚本都步骤会导致unity重新编译。没有找到获取编译完成状态的方法,绕了一步,在text组件的节点上添加一个标记脚本,用于第三步挂载Inspector节点

	private static void Text2TextMeshPro(string path,bool changeScript )
    {
        var obj = AssetDatabase.LoadAssetAtPath<GameObject>(path);
        var prefab = PrefabUtility.InstantiatePrefab(obj) as GameObject;
       
        if (prefab)
        {
            if (prefab != null)
            {
                SerializedObject serializedObject = new SerializedObject(prefab);
#region 添加标记,如果不需要第三步挂载节点,这里不需要
                var scripts = prefab.GetComponents<MonoBehaviour>().Where(s=>!IsUIComponent(s)).ToList();
                foreach (var script in scripts)
                {
                    
                    var components = script.GetComponents<Component>().Where(s=>!IsUIComponent(s)).ToList();
                    foreach (var component in components)
                    {
                        
                        // var componentType = component.GetType();
                        var fields = component.GetAllFields().Where(f => f.FieldType == typeof(UnityEngine.UI.Text)).ToList();
                     
                        foreach (var field in fields)
                        {
                            if (field.FieldType == typeof(UnityEngine.UI.Text))
                            {
                                if (field.GetValue(component) == null)
                                {
                                    continue;
                                }
                                var textComponent = field.GetValue(component) as UnityEngine.UI.Text;
                                var identifier = textComponent.GetOrAddComponent<MyIdentifier>();
                                // 设置标识符为子对象的名称
                                identifier.SetIdentifier(field.Name);
                            }
                        }
                    }
                    
    #endregion
                    if(changeScript)//替换脚本
                    {
                        ReplaceScript(MonoScript.FromMonoBehaviour(script));
                    }
                }
            }


            Text[] list = prefab.GetComponentsInChildren<Text>(true);
            for (int i = 0; i < list.Length; i++)
            {
                Text text = list[i];
                ChangeText2TMP(text);
            }

            Debug.LogError("保存预制体");
        }

        PrefabUtility.SaveAsPrefabAsset(prefab, path, out bool success);
        DestroyImmediate(prefab);
        if (!success)
        {
            Debug.LogError($"预制体:{path} 保存失败!");
        }
    }

 	private static bool IsUIComponent(Component component)
    {
        return component.GetType().IsSubclassOf(typeof(UnityEngine.UI.Graphic));
    }

//这个脚本是单独的脚本,只是用来做个标记,不要放在Editor下

public class MyIdentifier : MonoBehaviour
{
    // [HideInInspector]
    public string identifier;

    public void SetIdentifier(string id)
    {
        identifier = id;
    }
}

3.替换脚本中的Text,注意添加对应的using TMPro, 组件是 TextMeshProUGUI而不是TextMeshPro

private static void ReplaceScript(MonoScript script)
    {
        var listPattern = new List<string>()
        {
            " Text ","<Text>","Text "
        };
        var listPatternReplace = new List<string>()
        {
            " TextMeshProUGUI ","<TextMeshProUGUI>","TextMeshProUGUI "
        };
        var text = "";
        var path = AssetDatabase.GetAssetPath(script);
        text = File.ReadAllText(path);
        if (!text.Contains("using TMPro;"))
        {
            text = $@"using TMPro;
{text}
";
        }
        for (var i = 0; i < listPattern.Count; i++)
        {
            var matches = new List<Match>();
            var pattern = listPattern[i];
            var regex = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Multiline);
            
            // 找到所有匹配的Button
            var tempMatches = regex.Matches(text);
            matches.AddRange(tempMatches.Cast<Match>());
            foreach (var match in matches)
            {
                var value = match.Value;
                var newValue = listPatternReplace[i];
                text = text.Replace(value, newValue);
            }
            
        }
        
        File.WriteAllText(path, text);

        AssetDatabase.Refresh();
    }

3.批量处理

 [MenuItem("Assets/工具/Text转TMPro(同时修改脚本)")]
    public static void SetSelectedMonsterPrefabsValue1()
    {
        Debug.Log($"数量{Selection.gameObjects.Length}");
        if (Selection.gameObjects.Length == 0)
        {
            return;
        }

        foreach (var obj in Selection.gameObjects)
        {
            var path = AssetDatabase.GetAssetPath(obj);
            Text2TextMeshPro(path,true);
        }
    }

3.重新挂载节点

上一步做了标记脚本,这里根据新脚本的属性获取挂在有标记脚本的节点,并且缓存标记和属性名相同的节点,进行绑定就可以了

  	[MenuItem("Assets/工具/Text转TMPro(重新赋值)")]
    public static void GetSelectedScript()
    {
        Debug.Log($"数量{Selection.gameObjects.Length}");
        if (Selection.gameObjects.Length == 0)
        {
            return;
        }

        foreach (var obj in Selection.gameObjects)
        {
            var path = AssetDatabase.GetAssetPath(obj);
            var prefab1 = AssetDatabase.LoadAssetAtPath<GameObject>(path);
            var prefab = PrefabUtility.InstantiatePrefab(prefab1) as GameObject;
            // var prefab = PrefabUtility.LoadPrefabContents(path);
            if (prefab != null)
            {
                var idList = prefab.GetComponentsInChildren<MyIdentifier>(true).ToList();
                SerializedObject serializedObject = new SerializedObject(prefab);
                var scripts = prefab.GetComponents<MonoBehaviour>().Where(s=>!IsUIComponent(s)).ToList();
                foreach (var script in scripts)
                {
                    var components = script.GetComponents<Component>().Where(s=>!IsUIComponent(s)).ToList();
                    foreach (var component in components)
                    {
                        var fields = component.GetAllFields();   
                        foreach (var field in fields)
                        {
                            if (field.FieldType == typeof(TextMeshProUGUI))
                            {
                                for (var i = 0; i < idList.Count; i++)
                                {
                                    if (idList[i].identifier == field.Name)
                                    {
                                        field.SetValue(script, idList[i].GetComponent<TextMeshProUGUI>());
                                        var identifier = idList[i];
                                        idList.Remove(idList[i]);
                                        DestroyImmediate(identifier);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            PrefabUtility.SaveAsPrefabAsset(prefab, path, out bool success);
            DestroyImmediate(prefab);
            if (!success)
            {
                Debug.LogError($"预制体:{path} 保存失败!");
            }
        }
    }

完整脚本

using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using TMPro;
using Unity.VisualScripting;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;

public class TextToTMPro : Editor
{
    
    [MenuItem("Assets/工具/Text转TMPro(同时修改脚本)")]
    public static void SetSelectedMonsterPrefabsValue1()
    {
        Debug.Log($"数量{Selection.gameObjects.Length}");
        if (Selection.gameObjects.Length == 0)
        {
            return;
        }

        foreach (var obj in Selection.gameObjects)
        {
            var path = AssetDatabase.GetAssetPath(obj);
            Text2TextMeshPro(path,true);
        }
    }
    [MenuItem("Assets/工具/Text转TMPro(prefab)")]
    public static void SetSelectedMonsterPrefabsValue2()
    {
        Debug.Log($"数量{Selection.gameObjects.Length}");
        if (Selection.gameObjects.Length == 0)
        {
            return;
        }

        foreach (var obj in Selection.gameObjects)
        {
            var path = AssetDatabase.GetAssetPath(obj);
            Text2TextMeshPro(path,false);
        }
    }
    private static void Text2TextMeshPro(string path,bool changeScript )
    {
        var prefab1 = AssetDatabase.LoadAssetAtPath<GameObject>(path);
        var prefab = PrefabUtility.InstantiatePrefab(prefab1) as GameObject;
        // var prefab = PrefabUtility.LoadPrefabContents(path);
        if (prefab)
        {
            if (prefab != null)
            {
                SerializedObject serializedObject = new SerializedObject(prefab);
                var scripts = prefab.GetComponents<MonoBehaviour>().Where(s=>!IsUIComponent(s)).ToList();
                
                foreach (var script in scripts)
                {
                    
                    var components = script.GetComponents<Component>().Where(s=>!IsUIComponent(s)).ToList();
                    foreach (var component in components)
                    {
                        
                        // var componentType = component.GetType();
                        var fields = component.GetAllFields().Where(f => f.FieldType == typeof(UnityEngine.UI.Text)).ToList();
                     
                        foreach (var field in fields)
                        {
                            if (field.FieldType == typeof(UnityEngine.UI.Text))
                            {
                                if (field.GetValue(component) == null)
                                {
                                    continue;
                                }
                                var textComponent = field.GetValue(component) as UnityEngine.UI.Text;
                                var identifier = textComponent.GetOrAddComponent<MyIdentifier>();
                                // 设置标识符为子对象的名称
                                identifier.SetIdentifier(field.Name);
                            }
                        }
                    }
                    if(changeScript)
                    {
                        ReplaceScript(MonoScript.FromMonoBehaviour(script));
                    }
                }
            }


            Text[] list = prefab.GetComponentsInChildren<Text>(true);
            for (int i = 0; i < list.Length; i++)
            {
                Text text = list[i];
                ChangeText2TMP(text);
            }

            Debug.LogError("保存预制体");
        }

        PrefabUtility.SaveAsPrefabAsset(prefab, path, out bool success);
        DestroyImmediate(prefab);
        if (!success)
        {
            Debug.LogError($"预制体:{path} 保存失败!");
        }
    }
    
    private static bool IsUIComponent(Component component)
    {
        return component.GetType().IsSubclassOf(typeof(UnityEngine.UI.Graphic));
    }

    private static void ChangeText2TMP(Text text)
    {
        Transform target = text.transform;
        Vector2 size = text.rectTransform.sizeDelta;
        string strContent = text.text;
        Color color = text.color;
        int fontSize = text.fontSize;
        FontStyle fontStyle = text.fontStyle;
        TextAnchor textAnchor = text.alignment;
        bool richText = text.supportRichText;
        HorizontalWrapMode horizontalWrapMode = text.horizontalOverflow;
        VerticalWrapMode verticalWrapMode = text.verticalOverflow;
        bool raycastTarget = text.raycastTarget;
        GameObject.DestroyImmediate(text);

        TextMeshProUGUI textMeshPro = target.gameObject.AddComponent<TextMeshProUGUI>();

        textMeshPro.rectTransform.sizeDelta = size;
        textMeshPro.text = strContent;
        textMeshPro.color = color;
        textMeshPro.fontSize = fontSize;
        textMeshPro.fontStyle = fontStyle == FontStyle.BoldAndItalic ? FontStyles.Bold : (FontStyles)fontStyle;
        switch (textAnchor)
        {
            case TextAnchor.UpperLeft:
                textMeshPro.alignment = TextAlignmentOptions.TopLeft;
                break;
            case TextAnchor.UpperCenter:
                textMeshPro.alignment = TextAlignmentOptions.Top;
                break;
            case TextAnchor.UpperRight:
                textMeshPro.alignment = TextAlignmentOptions.TopRight;
                break;
            case TextAnchor.MiddleLeft:
                textMeshPro.alignment = TextAlignmentOptions.MidlineLeft;
                break;
            case TextAnchor.MiddleCenter:
                textMeshPro.alignment = TextAlignmentOptions.Midline;
                break;
            case TextAnchor.MiddleRight:
                textMeshPro.alignment = TextAlignmentOptions.MidlineRight;
                break;
            case TextAnchor.LowerLeft:
                textMeshPro.alignment = TextAlignmentOptions.BottomLeft;
                break;
            case TextAnchor.LowerCenter:
                textMeshPro.alignment = TextAlignmentOptions.Bottom;
                break;
            case TextAnchor.LowerRight:
                textMeshPro.alignment = TextAlignmentOptions.BottomRight;
                break;
        }

        textMeshPro.richText = richText;
        if (verticalWrapMode == VerticalWrapMode.Overflow)
        {
            textMeshPro.enableWordWrapping = true;
            textMeshPro.overflowMode = TextOverflowModes.Overflow;
        }
        else
        {
            textMeshPro.enableWordWrapping = horizontalWrapMode == HorizontalWrapMode.Overflow ? false : true;
        }

        textMeshPro.raycastTarget = raycastTarget;
        var font = AssetDatabase.LoadAssetAtPath<TMP_FontAsset>("Assets/Art/Font/SourceHanSansCN-Medium SDF.asset");
        textMeshPro.font = font;
    }
    [MenuItem("Assets/工具/脚本Text转TMPro")]
    public static void ReplaceAllScriptTxt2MeshPro()
    {
        for(var i = 0;i<Selection.objects.Length;i++)
        {
            var obj = Selection.objects[i];
            var path = AssetDatabase.GetAssetPath(obj);
            if (path.EndsWith(".cs"))
            {
                var script = AssetDatabase.LoadAssetAtPath<MonoScript>(path);
                ReplaceScript(script);
            }
        }
    }
    private static void ReplaceScript(MonoScript script)
    {
        var listPattern = new List<string>()
        {
            " Text ","<Text>","Text "
        };
        var listPatternReplace = new List<string>()
        {
            " TextMeshProUGUI ","<TextMeshProUGUI>","TextMeshProUGUI "
        };
        var text = "";
        var path = AssetDatabase.GetAssetPath(script);
        text = File.ReadAllText(path);
        if (!text.Contains("using TMPro;"))
        {
            text = $@"using TMPro;
{text}
";
        }
        for (var i = 0; i < listPattern.Count; i++)
        {
            var matches = new List<Match>();
            var pattern = listPattern[i];
            var regex = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Multiline);
            
            // 找到所有匹配的Button
            var tempMatches = regex.Matches(text);
            matches.AddRange(tempMatches.Cast<Match>());
            foreach (var match in matches)
            {
                var value = match.Value;
                var newValue = listPatternReplace[i];
                text = text.Replace(value, newValue);
            }
            
        }
        
        File.WriteAllText(path, text);

        AssetDatabase.Refresh();
    }
   
    

    [MenuItem("Assets/工具/Text转TMPro(重新赋值)")]
    static void GetSelectedScript()
    {
        Debug.Log($"数量{Selection.gameObjects.Length}");
        if (Selection.gameObjects.Length == 0)
        {
            return;
        }

        foreach (var obj in Selection.gameObjects)
        {
            var path = AssetDatabase.GetAssetPath(obj);
            var prefab1 = AssetDatabase.LoadAssetAtPath<GameObject>(path);
            var prefab = PrefabUtility.InstantiatePrefab(prefab1) as GameObject;
            // var prefab = PrefabUtility.LoadPrefabContents(path);
            if (prefab != null)
            {
                var idList = prefab.GetComponentsInChildren<MyIdentifier>(true).ToList();
                SerializedObject serializedObject = new SerializedObject(prefab);
                var scripts = prefab.GetComponents<MonoBehaviour>().Where(s=>!IsUIComponent(s)).ToList();
                foreach (var script in scripts)
                {
                    var components = script.GetComponents<Component>().Where(s=>!IsUIComponent(s)).ToList();
                    foreach (var component in components)
                    {
                        var fields = component.GetAllFields();   
                        foreach (var field in fields)
                        {
                            if (field.FieldType == typeof(TextMeshProUGUI))
                            {
                                for (var i = 0; i < idList.Count; i++)
                                {
                                    if (idList[i].identifier == field.Name)
                                    {
                                        field.SetValue(script, idList[i].GetComponent<TextMeshProUGUI>());
                                        var identifier = idList[i];
                                        idList.Remove(idList[i]);
                                        DestroyImmediate(identifier);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            PrefabUtility.SaveAsPrefabAsset(prefab, path, out bool success);
            DestroyImmediate(prefab);
            if (!success)
            {
                Debug.LogError($"预制体:{path} 保存失败!");
            }
        }
    }
}
  • 21
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值