Unity编辑器:搜索挂有UILocalize脚本的GamObject

发表于2018-07-19
评论0 3.2k浏览
本篇文章和大家介绍下如何实现指定文件夹(用鼠标选择Project目录下一个文件夹)下所有挂载UILocalize脚本的GameObject;

先说下怎么在Assets目录下搜索所有的prefab,代码如下:
<span style="font-family:SimSun;font-size:12px;">    /// <summary>
    /// 寻找所有类型的预制体
    /// </summary>
    /// <returns></returns>
    public static Object[] Search()
    {
        string[] mExtensions = new string[] { ".prefab" };
        string[] paths = AssetDatabase.GetAllAssetPaths();
        BetterList<Object> list = new BetterList<Object>();
        for (int i = 0; i < paths.Length; ++i)
        {
            string path = paths[i];
            bool valid = false;
            for (int k = 0; k < mExtensions.Length; ++k)
            {
                if (path.EndsWith(mExtensions[k], System.StringComparison.OrdinalIgnoreCase))
                {
                    valid = true;
                    break;
                }
            }
            if (!valid) continue;
            Object obj = AssetDatabase.LoadMainAssetAtPath(path);
            if (obj == null || list.Contains(obj)) continue;
            list.Add(obj);
        }
        EditorUtility.ClearProgressBar();
        //if()
        return list.ToArray();
    }
</span>

关于AssetDatabase方法:

导入资源:
AssetDatabase.ImportAsset方法,Unity 只在需要时自动导入已拖放至该工程的资源,但也可能在脚本控制下导入这些资源。为此,您可以使用AssetDatabase.ImportAsset 类函数。您也可将额外的 AssetDatabase.ImportAssetOptions 类型参数传递至资源数据库 (AssetDatabase)

加载资源方法:
AssetDatabase.LoadAssetAtPath,AssetDatabase.LoadMainAssetAtPath,AssetDatabase.LoadAllAssetRepresentationsAtPath和AssetDatabase.LoadAllAssetsAtPath。

使用AssetDatabase 操作文件
Unity 将保留资源文件的元数据,您决不可使用文件系统创建、移动或删除它们。相反您可以AssetDatabase.Contains、AssetDatabase.CreateAsset、AssetDatabase.CreateFolder、AssetDatabase.RenameAsset、AssetDatabase.CopyAsset、AssetDatabase.MoveAsset、AssetDatabase.MoveAssetToTrash 和 AssetDatabase.DeleteAsset 进行相反上述操作

使用AssetDatabase.Refresh
修改完资源后,您应调用AssetDatabase.Refresh 将更改提交至数据库,并使其显示在工程中。
至于上面用到的AssetDatabase.GetAllAssetPaths(),不难看出是获取所有Assets下的路径,当然还有很多获取其他路径的方法,这里占时不写了。

但是需求改了要求搜索Scene/Hierarchy中所有挂载UILocalize脚本的GameObject,/(ㄒoㄒ)/~~好吧,不多说上代码:
<span style="font-family:SimSun;font-size:12px;">    /// <summary>
    /// 寻找场景中的GameObjec
    /// </summary>
    /// <returns></returns
    public static Object[] SearchScene()
    {
        GameObject[] pAllObjects = (GameObject[])Resources.FindObjectsOfTypeAll(typeof(GameObject));
        BetterList<Object> list = new BetterList<Object>();
        foreach (GameObject go in pAllObjects)
        {
            if (go.hideFlags != HideFlags.HideInHierarchy)
            {
                UnityEngine.Object parentObject = PrefabUtility.GetPrefabParent(go);
                string path = AssetDatabase.GetAssetPath(parentObject);
                Object obj = AssetDatabase.LoadMainAssetAtPath(path);
                if (obj == null || list.Contains(obj)) continue;
                if (!list.Contains(obj))
                    list.Add(obj);
            }
        }
        EditorUtility.ClearProgressBar();
        return list.ToArray();
}
</span>

搜索某个路径(填写一个路径)下所有挂载UILocalize脚本的GameObject:
<span style="font-family:SimSun;font-size:12px;">    // <summary>
    /// 搜索填写路径文件夹下的预制物体
    /// </summary>
    /// <returns></returns>
	public static Object[] SearchFolder()
    {
        string[] mExtensions = new string[] { ".prefab" };
        string[] paths = AssetDatabase.GetAllAssetPaths();
        BetterList<Object> list = new BetterList<Object>();
        for (int i = 0; i < paths.Length; ++i)
        {
            string path = paths[i];
            if (path.Contains(_PathFolder)) {
                bool valid = false;
                for (int k = 0; k < mExtensions.Length; ++k)
                {
                    if (path.EndsWith(mExtensions[k], System.StringComparison.OrdinalIgnoreCase))
                    {
                        valid = true;
                        break;
                    }
                }
                if (!valid) continue;
                Object obj = AssetDatabase.LoadMainAssetAtPath(path);
                if (obj == null || list.Contains(obj)) continue;
                list.Add(obj);
            }
        }
        EditorUtility.ClearProgressBar();
        return list.ToArray();
    }
</span>

代码跟搜索所有的物体差不多,只是加了个判断。
接下来是:指定文件夹(用鼠标选择Project目录下一个文件夹)下所有挂载UILocalize脚本的GameObject:
<span style="font-family:SimSun;font-size:12px;">    /// <summary>
    /// 搜索指定文件夹下的预制物体(与SearchFolder区别:此方法不需要填写路径,但是要:先在prproject目录下选择一个文件夹)
    /// </summary>
    /// <returns></returns>
	public static Object[] SearchMominateFolder()
    {
        var objs = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
        EditorUtility.ClearProgressBar();
        return objs;
    }
</span>
代码很简单,5行搞定。

这里你会疑问,我怎么找啊?接下来我们写一个找的方法:
<span style="font-family:SimSun;font-size:12px;">    private void FindAllObj(System.Action<GameObject> mAction, SearchPath mType)
    {
        Info = string.Empty;
        Object[] allObj = null;
        switch (mType)
        {
            case SearchPath.Assets:
                allObj = Search();
                break;
            case SearchPath.SceneAndHierarchy:
                allObj = SearchScene();
                break;
            case SearchPath.PathFolder:
                allObj = SearchFolder();
                break;
            case SearchPath.MominatePathFolder:
                allObj = SearchMominateFolder();
                break;
            default:
                break;
        }
        if (allObj == null)
            return;
        _count = 0;
        _listPath.Clear();
        _sts.Length = 0;
        //_sts.Append("列表:(更加详细的内容请参看项目根目录下PrefabUILocalize.txt)\n");
        for (int i = 0; i < allObj.Length; i++)
        {
            if (PrefabUtility.GetPrefabType(allObj[i]) == PrefabType.Prefab)
            {
                GameObject _item_allObj = allObj[i] as GameObject;
                mAction(_item_allObj);
            }
            EditorUtility.DisplayProgressBar("资源分析中", "请耐心等候...", (float)i / allObj.Length);
        }
        _listPath.Sort();
        for (int i = 0; i < _listPath.Count; i++)
        {  
            _sts.AppendLine(string.Format("{0}.{1}", i + 1, _listPath[i]));
        }
        Info = _sts.ToString();
        EditorUtility.ClearProgressBar();
        EditorUtility.DisplayDialog("消息", string.Format("搜索分析完成,共搜索出相关物体{0}个,更加详细的内容请参看项目根目录下PrefabUILocalize.txt", _count.ToString()), "OK");
   }
     /// <summary>
    /// 寻找挂有UILocalize脚本的预制物体
    /// </summary>
    /// <param name="go"></param>
    protected virtual void FindUILocalize(GameObject go)
    {
        if (go.GetComponent<UILocalize>() != null)
        {
            _count++;
            string goName = go.name;
            Transform tf = go.transform;
            while (tf.parent != null)
            {
                goName = tf.parent.name + "/" + goName;
                tf = tf.parent;
            }
            _strTempInfo = string.Format("{0}/{1}", AssetDatabase.GetAssetPath(go), goName);
            if (!_listPath.Contains(_strTempInfo))
            {
                _listPath.Add(_strTempInfo);
            }
        }
        foreach (Transform childTF in go.transform)
        {
            FindUILocalize(childTF.gameObject);
        }
    }
</span>

但是需求又加了一条:要求写到一个文件里,代码如下。
<span style="font-family:SimSun;font-size:12px;">private void CreateFile(string info)
    {
        using (StreamWriter sw = new StreamWriter(@"PrefabUILocalize.txt"))
        {
            sw.Write(info);
            sw.Close();
            sw.Dispose();
        }
}
</span>

写完了,那该怎么应用到Unity呢?接下来就要用到using UnityEditor;
<span style="font-family:SimSun;font-size:12px;">    protected override void DarwInfo()
    {
        base.DarwInfo();
        EditorGUILayout.BeginHorizontal();
        _PathFolder = EditorGUILayout.TextField("请输入路径(区分大小写)", _PathFolder);
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.BeginHorizontal();
        if (GUILayout.Button("寻找指定路径下挂载Localize脚本的预制体"))
        {
            FindAllObj(this.FindUILocalize, SearchPath.MominatePathFolder);
        }
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.BeginHorizontal();
        if (GUILayout.Button("寻找填写路径下挂载Localize脚本的预制体"))
        {
            FindAllObj(this.FindUILocalize, SearchPath.PathFolder);
        }
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.BeginHorizontal();
        if (GUILayout.Button("搜索场景中挂载Localize脚本的预制体"))
        {
            FindAllObj(this.FindUILocalize, SearchPath.SceneAndHierarchy);
        }
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.BeginHorizontal();
        if (GUILayout.Button("搜索Assets目录下挂载Localize脚本的预制体"))
        {
            FindAllObj(this.FindUILocalize, SearchPath.Assets);
        }
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.BeginHorizontal();
        if (GUILayout.Button("清空表中数据"))
        {
            Info = string.Empty;
        }
        EditorGUILayout.EndHorizontal();
    }
</span>
<span style="font-family:SimSun;font-size:12px;">using UnityEngine;
using UnityEditor;
using System.Collections;
public class ToolsManager_OTT : Editor
{
    [MenuItem("Tools_OTT/搜索含有UILocalize预制物体")]
    public static void ItemFindLocationInfo()
    {
        EditorWindow.GetWindow<FindUILocalizeObj_OTT>(false, "搜索含有UILocalize预制物体", true).Show();
    }
}</span>

最后效果:

来自:https://blog.csdn.net/nliki/article/details/51911878

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引