在 Unity 中使用 Resources.Load 时搜索所有子文件夹

Tob*_*obl 5 c# unity-game-engine

是否可以让 Resources.Load(name, type) 不仅在基本资源文件夹/指定的子文件夹中搜索合适的资源,而且还可以在资源下的完整子文件夹结构中搜索合适的资源?

示例文件夹结构

Resources
  - Subfolder
    - image.png
Run Code Online (Sandbox Code Playgroud)

我想要像 Resources.Load("image", typeof(Texture2D)) 这样的东西来返回图像,而用户不必指定“子文件夹/图像”。

我知道它很丑陋,但它应该是一个“将它放入你的混在一起的项目中,而不用担心你的文件夹结构”类型的实用程序脚本,我不知道子文件夹。

use*_*227 5

接受的答案仅在编辑器上下文中有效,在构建游戏后不起作用。资源文件夹在构建游戏时被打包,并且将不再是可以使用 Directory.GetDirectories 循环的文件层次结构。使其发挥作用的唯一方法是在编辑器上下文中保存所有文件路径,并使用此文件层次结构在运行时加载资源。在我的项目中,我使用以下代码向使用资源文件夹中资源的组件添加一个按钮,名为CharacterGen。单击此按钮时,Resources 文件夹中所有子文件夹中的所有 png 文件都会保存到 CharacterGen 具有的名为 filePaths 的公共属性中。

[CustomEditor(typeof(CharacterGen))]
public class RefreshCharacterList : Editor
{
    CharacterGen charGen;
    public void OnEnable()
    {
        charGen = (CharacterGen)target;
    }

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        if (GUILayout.Button("Load resource paths"))
        {
            List<String> paths = new List<string>();
            LoadPathsRecursive("", ref paths);
            charGen.filePaths = paths;
            EditorUtility.SetDirty(charGen); //original post didn't have this line, but this is needed to make sure your changes are saved. 
    
        }
    }


    void LoadPathsRecursive(string path, ref List<string> paths)
    {
        var fullPath = Application.dataPath + "/Resources/" + path;
        Debug.Log("fullPath: " + fullPath);
        DirectoryInfo dirInfo = new DirectoryInfo(fullPath);
        foreach(var file in dirInfo.GetFiles())
        {
            if (file.Name.Contains(".PNG") && !file.Name.Contains(".meta"))
            {
                paths.Add(path + "/" + file.Name.Replace(".PNG", ""));
            }
        }
      
        foreach (var dir in dirInfo.GetDirectories())
        {
            LoadPathsRecursive(path + "/" + dir.Name, ref paths);
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

在CharacterGen中,我后来使用单击按钮时保存的路径调用Resources.Load。

foreach (var filePath in filePaths)
{
   var loadedSprite = Resources.Load<Sprite>(filePath);
   //Do something with loadedSprite
}

Run Code Online (Sandbox Code Playgroud)

编辑:我在原来的帖子中没有提到一个重要的细节。filePaths 是一个 Monobehaviour 字段,我用 [SerializeField] 标记它(或者可以将其标记为公共),以便 Unity 实际上序列化该字段的值并将其包含在构建中。


小智 3

无法更改Resouces.Load()静态方法功能,它是 Unity 内部的。但是,您可以编写自己的自定义类来执行您所需的功能。该代码需要找到文件夹内的所有目录Resources并搜索文件。我们来称呼班级吧ResourcesExtension

public class ResourcesExtension
{
    public static string ResourcesPath = Application.dataPath+"/Resources";

    public static UnityEngine.Object Load(string resourceName, System.Type systemTypeInstance) 
    {
    string[] directories = Directory.GetDirectories(ResourcesPath,"*",SearchOption.AllDirectories);
    foreach (var item in directories)
    {
        string itemPath = item.Substring(ResourcesPath.Length+1);
        UnityEngine.Object result = Resources.Load(itemPath+"\\"+resourceName,systemTypeInstance);
        if(result!=null)
            return result;
    }
    return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你需要做的就是调用静态方法。

ResourcesExtension.Load("image", typeof(Texture2D))
Run Code Online (Sandbox Code Playgroud)