简体   繁体   中英

How do I loop over all Assets folders and sub folders and get to a list all the prefabs in this folders?

This code get all the sub folders in a Assets specific folder.

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);
        }
    }
}

And this get all the prefabs from a specific folder but when I type the folder name:

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);
                }
            }
        }
    }

I want to combine both codes so when I make right click and select Get Path it will get all the prefabs from the selected path the right click on the path and the path all sub folders recursive.

Example:

Assets
  Folder1
  Folder2
    Folder3
     Folder4
     Folder5
  Folder6

If in the Assets I make mouse right click on the folder Folder2 and then select from the menu Get Path I want it to get all the prefabs from Folder2 and all the sub folders under Folder2. So In the end I will have a List of all the paths with the folders:

Folder2\1.prefab
Folder2\Folder3\2.prefab
Folder2\Folder3\3.prefab
Folder2\Folder4\4.prefab

In the end my goal is to be able to add to each prefab a component for example a Rigidbody. So if I have a folder with the 10 prefabs and under it 30 sub folders with more 200 prefabs then get all the folders and prefabs and add a component/s to all the prefabs in all folders.

Here is an alternative and simple way to do this.

string[] files = Directory.GetFiles("DirectoryPath", "*.prefab", SearchOption.AllDirectories);

You can use "Resources.Load("[path]/[filename]") as [Class]" this will give you the asset, prefab, sprite etc you need. Important to note that this will only look in the folder "Resources" in the asset folder (the root in the unity project), so you have to create a "Resources" folder. This is also just a good idea because it can be very slow to look trough all files so this ensures it only looks at the important files. So you can use Vivek nuna's solution to get the file locations and Resources.Load to get the asset: For more information look here: https://docs.unity3d.com/ScriptReference/Resources.html

Hope this helps!

To get actual prefab from path, use AssetDatabase.LoadAssetAtPath(path) and related methods.

It only works in editor, but I guess thats what you need

This is what I wanted and working good for my case:

In the Assets right click on any Folder and then click on Add Components. It will loop all the folders and sub folders of the folder you did right click Add Components. Then it will find all the prefabs add to them a Rigidbody and save the changes.

Depending on how many prefabs you have it might be a bit slowly but it's doing the job.

Things to add:

Options to add more components or multiple components.

Creating a log/text file with all the changes made prefabs names what changes made and when.

Undo if there an option to make undo on Assets or to make the undo using the text file reading the changes made and revert back.

Backup: Once adding components to make a backup first in a temp folder of the original prefabs (could be also use for undo cases ).

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);
            }
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM