首页 > 解决方案 > 在 Unity 项目中的所有游戏对象中查找和替换文本

问题描述

我有几个要求在整个项目中更新一些文本。在代码中进行查找和替换很容易,但我想实现一个工具来查看所有游戏对象。不幸的是,我可以抓取场景中的所有游戏对象,但是我还没有找到一个解决方案来抓取项目中的所有游戏对象。有没有人有什么建议?

这是我目前的做法:

using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using EditorPlayerSettings = UnityEditor.PlayerSettings;

namespace UnityEditor.XCodeEditor
{
    public class FindAndReplaceToolbar : EditorWindow
    {
        private const string TAG = "FindAndReplace";

        string mOldValue = string.Empty;
        string mNewValue = string.Empty;

        [MenuItem("Window/Find And Replace")]
        void Init()
        {
            var window = GetWindow<FindAndReplaceToolbar>(false, "Find And Replace Toolbar");
            window.minSize = new Vector2(10, 10);
            window.Show();
        }

        void OnGUI()
        {
            GUILayout.BeginHorizontal();
            {
                mOldValue = EditorGUILayout.TextField("Find: ", mOldValue, GUILayout.ExpandWidth(true));
            }
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            {
                mNewValue = EditorGUILayout.TextField("Replace: ", mNewValue, GUILayout.ExpandWidth(true));
            }
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();

            if (GUILayout.Button("Find and Replace"))
            {
                FindAndReplace();
            }

            GUILayout.EndHorizontal();
        }

        #region Find And Replace Helper
        public void FindAndReplace()
        {
            Debug.Log($"{TAG} Started: ({mOldValue} - {mNewValue})");

            foreach (var textMeshProUGUI in GetAllTextMeshProUGUIsInScene())
            {
                if (textMeshProUGUI.text.Contains(mOldValue))
                {
                    Debug.Log($"{TAG} Replaced {mOldValue} in {textMeshProUGUI.name} with {mNewValue} (See {GetFileName(textMeshProUGUI.transform)})");
                    textMeshProUGUI.text = textMeshProUGUI.text.Replace(mOldValue, mNewValue);
                }
            }

            Debug.Log($"{TAG} Finished: ({mOldValue} - {mNewValue})");
        }

        public List<TextMeshProUGUI> GetAllTextMeshProUGUIsInScene()
        {
            List<TextMeshProUGUI> objectsInScene = new List<TextMeshProUGUI>();

            foreach (TextMeshProUGUI go in (TextMeshProUGUI[]) Resources.FindObjectsOfTypeAll(typeof(TextMeshProUGUI)))
            {
                if (!EditorUtility.IsPersistent(go.transform.root.gameObject) && !(go.hideFlags == HideFlags.NotEditable || go.hideFlags == HideFlags.HideAndDontSave))
                {
                    objectsInScene.Add(go);
                }
            }

            return objectsInScene;
        }

        public static string GetFileName(Transform transform)
        {
            try
            {
                var parent = transform;

                while (parent.parent != null)
                {
                    parent = parent.parent;
                }

                return parent.name;
            }
            catch (Exception)
            {
                return transform.name;
            }
        }
        #endregion Find And Replace Helper
    }
}

标签: c#unity3d

解决方案


@hijinxbassist 为我指明了正确的方向。这是我目前的解决方案:

using System;
using System.IO;
using UnityEngine;
using EditorPlayerSettings = UnityEditor.PlayerSettings;

namespace UnityEditor.XCodeEditor
{
    [InitializeOnLoad]
    public class FindAndReplaceToolbar : EditorWindow
    {
        private const string TAG = "FindAndReplace";

        private string mOldValue = string.Empty;
        private string mNewValue = string.Empty;

        static FindAndReplaceToolbar()
        {
            Debug.Log($"{TAG} InitializeOnLoad");
        }

        [MenuItem("Window/Find And Replace")]
        static void Init()
        {
            var window = GetWindow<FindAndReplaceToolbar>(false, "Find And Replace Toolbar");
            window.minSize = new Vector2(10, 10);
            window.Show();
        }

        void OnGUI()
        {
            GUILayout.BeginHorizontal();
            {
                mOldValue = EditorGUILayout.TextField("Find: ", mOldValue, GUILayout.ExpandWidth(true));
            }
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            {
                mNewValue = EditorGUILayout.TextField("Replace: ", mNewValue, GUILayout.ExpandWidth(true));
            }
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();

            if (GUILayout.Button("Find and Replace"))
            {
                FindAndReplace();
            }

            GUILayout.EndHorizontal();
        }

        public void FindAndReplace()
        {
            Debug.Log($"{TAG}: Started: ({mOldValue} - {mNewValue})");

            string[] assetGUIDs = AssetDatabase.FindAssets("t:Object");

            for (int i = 0; i < assetGUIDs.Length; i++)
            {
                try
                {
                    string guid = assetGUIDs[i];

                    string assetFilePath = AssetDatabase.GUIDToAssetPath(guid);

                    string assetFile = File.ReadAllText(assetFilePath);

                    if (assetFile.Contains(mOldValue))
                    {
                        assetFile = assetFile.Replace(mOldValue, mNewValue);

                        File.WriteAllText(assetFilePath, assetFile);

                        Debug.Log($"{TAG}: Replaced {mOldValue} with {mNewValue} in Asset: [{Path.GetFileName(assetFilePath)}] (Type: {AssetDatabase.GetMainAssetTypeAtPath(assetFilePath)})");
                    }
                }
                catch (Exception e)
                {
                    Debug.Log($"{TAG}: {e.Message}");
                }
            }

            Debug.Log($"{TAG}: Finished: ({mOldValue} - {mNewValue})");
        }
    }
}

推荐阅读