如何循环遍历所有资源文件夹和子文件夹,并列出这些文件夹中的所有预制品列表?

4

这段代码获取了指定 Assets 文件夹内的所有子文件夹。

using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;

public class AddComponents : Editor
{
    private static string GetClickedDirFullPath()
    {
        string clickedAssetGuid = Selection.assetGUIDs[0];
        string clickedPath = AssetDatabase.GUIDToAssetPath(clickedAssetGuid);
        string clickedPathFull = Path.Combine(Directory.GetCurrentDirectory(), clickedPath);

        FileAttributes attr = File.GetAttributes(clickedPathFull);
        return attr.HasFlag(FileAttributes.Directory) ? clickedPathFull : Path.GetDirectoryName(clickedPathFull);
    }

    private static string GetPath()
    {
        string path = GetClickedDirFullPath();
        int index = path.IndexOf("Assets");
        string result = path.Substring(index);

        return result;
    }

    private static string[] GetSubFoldersRecursive(string root)
    {
        var paths = new List<string>();

        // If there are no further subfolders then AssetDatabase.GetSubFolders returns 
        // an empty array => foreach will not be executed
        // This is the exit point for the recursion
        foreach (var path in AssetDatabase.GetSubFolders(root))
        {
            // add this subfolder itself
            paths.Add(path);

            // If this has no further subfolders then simply no new elements are added
            paths.AddRange(GetSubFoldersRecursive(path));
        }

        return paths.ToArray();
    }

    [MenuItem("Assets/Get Folders")]
    private static void GetFolders()
    {
        List<string> paths = new List<string>();
        string selectedPath = GetPath();
        var folders = GetSubFoldersRecursive(selectedPath);
        foreach (var path in folders)
        {
            paths.Add(path);
        }
    }
}

以下代码可从指定文件夹中获取所有预制体,但是当我输入文件夹名称时:

public List<string> prefabsPaths;

    public void AddComponentsToObjects()
    {
        prefabsPaths = new List<string>();

        string[] assetsPaths = AssetDatabase.GetAllAssetPaths();

        foreach (string assetPath in assetsPaths)
        {
            if (assetPath.Contains("Archanor"))
            {
                if (assetPath.Contains("Prefabs"))
                {
                    prefabsPaths.Add(assetPath);
                }
            }
        }
    }

我希望将两个代码合并,这样当我右键单击并选择“获取路径”时,它将获取所选路径中的所有prefab,包括右键单击的路径和该路径下的所有子文件夹(递归获取)。
示例:
Assets
  Folder1
  Folder2
    Folder3
     Folder4
     Folder5
  Folder6

如果我在资源中右键单击文件夹Folder2,然后从菜单中选择“获取路径”,我希望它能获取Folder2中所有预制件以及Folder2下的所有子文件夹。最终,我将获得包含所有文件夹路径的列表:
Folder2\1.prefab
Folder2\Folder3\2.prefab
Folder2\Folder3\3.prefab
Folder2\Folder4\4.prefab

最终目标是为每个预制件添加一个组件,例如Rigidbody。 因此,如果我有一个包含10个预制件的文件夹,并且其中有30个子文件夹和200多个预制件,则获取所有文件夹和预制件并在所有文件夹中的所有预制件上添加一个或多个组件。
4个回答

1
你可以使用"Resources.Load("[路径]/[文件名]") as [类]",这将为你提供所需的资源、预制件、精灵等。需要注意的是,这只会在资产文件夹中的“Resources”文件夹中查找(在Unity项目中的根目录),因此你必须创建一个“Resources”文件夹!这也是个好主意,因为查看所有文件可能非常缓慢,这样可以确保它只查看重要文件。因此,你可以使用Vivek nuna的解决方案来获取文件位置,并使用Resources.Load来获取资源。更多信息请参见:https://docs.unity3d.com/ScriptReference/Resources.html
希望能对你有所帮助!

1
似乎有人在这里问了同样的问题,这是链接:https://stackoverflow.com/questions/62165961/how-can-i-loop-over-sub-folders-in-assets-folder - Joanthan Ahrenkiel-Frellsen

1

要从路径获取实际的预制体,请使用AssetDatabase.LoadAssetAtPath(path)和相关方法。

它仅在编辑器中起作用,但我想这正是您所需要的。


1
这里有一种替代且简单的方法来完成这个任务。
string[] files = Directory.GetFiles("DirectoryPath", "*.prefab", SearchOption.AllDirectories);

1
它可以获取文件,但无法获取资源。我该如何添加组件?我需要将资源作为预制件获取,而不是作为硬盘上的文件。 - batshevagirl bat

0

这正是我想要的,对我的情况很有效:

在资源中右键单击任何文件夹,然后单击添加组件。它将循环文件夹及其子文件夹,找到所有预制体并向它们添加刚体并保存更改。

根据您拥有的预制体数量,可能会有点慢,但它正在完成工作。

需要添加的内容:

添加更多组件或多个组件的选项。

创建一个包含所有更改的预制体名称、更改内容和时间的日志/文本文件。

撤销:如果有在资源上进行撤销的选项,或者使用文本文件读取所做的更改并还原回去的选项。

备份:在添加组件之前,先在原始预制体的临时文件夹中进行备份(也可用于撤销情况)。

using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using UnityEditor;
using UnityEngine;

public class AddComponents : Editor
{
    private static string GetClickedDirFullPath()
    {
        string clickedAssetGuid = Selection.assetGUIDs[0];
        string clickedPath = AssetDatabase.GUIDToAssetPath(clickedAssetGuid);
        string clickedPathFull = Path.Combine(Directory.GetCurrentDirectory(), clickedPath);

        FileAttributes attr = File.GetAttributes(clickedPathFull);
        return attr.HasFlag(FileAttributes.Directory) ? clickedPathFull : Path.GetDirectoryName(clickedPathFull);
    }

    private static string GetPath()
    {
        string path = GetClickedDirFullPath();
        int index = path.IndexOf("Assets");
        string result = path.Substring(index);

        return result;
    }

    static List<string> paths = new List<string>();
    private static void GetFolders()
    {

        string selectedPath = GetPath();

        string[] assetsPaths = AssetDatabase.GetAllAssetPaths();

        foreach (string assetPath in assetsPaths)
        {
            if (assetPath.Contains(selectedPath))
            {
                if (assetPath.Contains("Prefabs"))
                {
                    paths.Add(assetPath);
                }
            }
        }
    }


    [MenuItem("Assets/Add Components")]
    public static void AddComponents()
    {
        GetFolders();

        for (int i = 0; i < paths.Count; i++)
        {
            if (File.Exists(paths[i]))
            {
                GameObject contentsRoot = PrefabUtility.LoadPrefabContents(paths[i]);

                // Modify Prefab contents.
                contentsRoot.AddComponent<Rigidbody>();

                // Save contents back to Prefab Asset and unload contents.
                PrefabUtility.SaveAsPrefabAsset(contentsRoot, paths[i]);
                PrefabUtility.UnloadPrefabContents(contentsRoot);
            }
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接