Unity读取文件夹内容

本代码只有读取文件夹中的图片、txt文档、子文件夹功能。可以将层级体现在一个list中。后续根据所需去遍历寻找对应的就好。

cs 复制代码
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Unity.VisualScripting;
using UnityEngine;

/// <summary>
/// 通用文件夹节点 - 可以表示任意层级的文件夹结构
/// </summary>
[Serializable]
public class FolderNode
{
    public string folderName;                          // 文件夹名称
    public string fullPath;                            // 完整路径

    public List<TextFile> textFiles;                   // 当前文件夹下的所有文本文件
    public List<ImageFile> imageFiles;                 // 当前文件夹下的所有图片文件
    public List<FolderNode> subFolders;                // 子文件夹列表

    public FolderNode(string name, string path)
    {
        folderName = name;
        fullPath = path;
        textFiles = new List<TextFile>();
        imageFiles = new List<ImageFile>();
        subFolders = new List<FolderNode>();
    }
}

/// <summary>
/// 文本文件数据
/// </summary>
[Serializable]
public class TextFile
{
    public string fileName;                            // 文件名(带扩展名)
    public string fileNameWithoutExtension;            // 文件名(不带扩展名)
    public string content;                             // 文件内容
    public string fullPath;                            // 完整路径

    public int GetAsInt()
    {
        int.TryParse(content, out int result);
        return result;
    }

    public float GetAsFloat()
    {
        float.TryParse(content, out float result);
        return result;
    }
}

/// <summary>
/// 图片文件数据
/// </summary>
[Serializable]
public class ImageFile
{
    public string fileName;                            // 文件名
    public string fileNameWithoutExtension;            // 文件名(不带扩展名)
    public Sprite sprite;                              // 加载的精灵
    public Texture2D texture;                          // 原始贴图
    public string fullPath;                            // 完整路径
}

/// <summary>
/// 通用数据加载器
/// </summary>
public class DataLoader : MonoBehaviour
{
    public static DataLoader Instance { get; private set; }

    private void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
        }
        else
        {
            Instance = this;
            // 可选:使单例对象在加载新场景时不被销毁
            // DontDestroyOnLoad(gameObject);
        }
    }

    [Header("配置")]
    [SerializeField] private string relativePath = "YourDataFolder";  // StreamingAssets 下的相对路径

    [Header("加载选项")]
    [SerializeField] private bool loadTextContent = true;              // 是否加载文本内容
    [SerializeField] private bool loadImages = true;                   // 是否加载图片
    [SerializeField] private bool keepTextureReference = false;        // 是否保留 Texture2D 引用(节省内存可关闭)

    [Header("运行时数据")]
    public FolderNode rootNode;                                        // 根节点

    public static FolderNode rootNode_Static;

    void Start()
    {
        LoadData();

        // 使用示例
        //ExampleUsage();

        rootNode_Static = rootNode;
    }

    /// <summary>
    /// 加载数据的入口方法
    /// </summary>
    public void LoadData()
    {
        string rootPath = Path.Combine(Application.streamingAssetsPath, relativePath);

        if (!Directory.Exists(rootPath))
        {
            Debug.LogError($"根目录不存在: {rootPath}");
            return;
        }

        Debug.Log($"开始加载: {rootPath}");
        float startTime = Time.realtimeSinceStartup;

        // 递归加载整个文件夹树
        rootNode = LoadFolderRecursive(rootPath);

        float loadTime = (Time.realtimeSinceStartup - startTime) * 1000f;
        Debug.Log($"加载完成!耗时: {loadTime:F2}ms");

        PrintStatistics(rootNode);
    }

    /// <summary>
    /// 递归加载文件夹及其所有内容
    /// </summary>
    FolderNode LoadFolderRecursive(string folderPath)
    {
        string folderName = Path.GetFileName(folderPath);
        FolderNode node = new FolderNode(folderName, folderPath);

        // 1. 加载当前文件夹下的所有文本文件
        if (loadTextContent)
        {
            string[] txtFiles = Directory.GetFiles(folderPath, "*.txt");
            foreach (string txtPath in txtFiles)
            {
                TextFile textFile = new TextFile
                {
                    fileName = Path.GetFileName(txtPath),
                    fileNameWithoutExtension = Path.GetFileNameWithoutExtension(txtPath),
                    content = File.ReadAllText(txtPath).Trim(),
                    fullPath = txtPath
                };
                node.textFiles.Add(textFile);
            }
        }

        // 2. 加载当前文件夹下的所有图片文件
        if (loadImages)
        {
            string[] imageExtensions = { "*.png", "*.jpg", "*.jpeg" };
            foreach (string ext in imageExtensions)
            {
                string[] imageFiles = Directory.GetFiles(folderPath, ext);
                foreach (string imgPath in imageFiles)
                {
                    ImageFile imageFile = LoadImage(imgPath);
                    if (imageFile != null)
                    {
                        node.imageFiles.Add(imageFile);
                    }
                }
            }
        }

        // 3. 递归加载所有子文件夹
        string[] subDirs = Directory.GetDirectories(folderPath);
        foreach (string subDir in subDirs)
        {
            FolderNode childNode = LoadFolderRecursive(subDir);
            node.subFolders.Add(childNode);
        }

        return node;
    }

    /// <summary>
    /// 加载单个图片文件
    /// </summary>
    ImageFile LoadImage(string imagePath)
    {
        try
        {
            byte[] fileData = File.ReadAllBytes(imagePath);
            Texture2D texture = new Texture2D(2, 2);

            if (texture.LoadImage(fileData))
            {
                Sprite sprite = Sprite.Create(
                    texture,
                    new Rect(0, 0, texture.width, texture.height),
                    new Vector2(0.5f, 0.5f)
                );

                ImageFile imageFile = new ImageFile
                {
                    fileName = Path.GetFileName(imagePath),
                    fileNameWithoutExtension = Path.GetFileNameWithoutExtension(imagePath),
                    sprite = sprite,
                    texture = keepTextureReference ? texture : null,
                    fullPath = imagePath
                };

                return imageFile;
            }
            else
            {
                Debug.LogError($"图片加载失败: {imagePath}");
                return null;
            }
        }
        catch (Exception e)
        {
            Debug.LogError($"读取图片异常: {imagePath}\n{e.Message}");
            return null;
        }
    }

    /// <summary>
    /// 打印统计信息
    /// </summary>
    void PrintStatistics(FolderNode node)
    {
        int totalFolders = 0;
        int totalTextFiles = 0;
        int totalImages = 0;

        CountRecursive(node, ref totalFolders, ref totalTextFiles, ref totalImages);

        Debug.Log($"=== 加载统计 ===");
        Debug.Log($"文件夹总数: {totalFolders}");
        Debug.Log($"文本文件总数: {totalTextFiles}");
        Debug.Log($"图片文件总数: {totalImages}");
    }

    void CountRecursive(FolderNode node, ref int folders, ref int texts, ref int images)
    {
        folders++;
        texts += node.textFiles.Count;
        images += node.imageFiles.Count;

        foreach (var child in node.subFolders)
        {
            CountRecursive(child, ref folders, ref texts, ref images);
        }
    }

    // ==================== 数据访问辅助方法 ====================

    /// <summary>
    /// 根据路径查找文件夹节点(支持相对路径)
    /// 例如: "Panel1/Items/Item01"
    /// </summary>
    public FolderNode FindFolder(string relativePath)
    {
        if (rootNode == null) return null;

        string[] parts = relativePath.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
        FolderNode current = rootNode;

        foreach (string part in parts)
        {
            current = current.subFolders.Find(f => f.folderName == part);
            if (current == null)
            {
                Debug.LogWarning($"未找到文件夹: {relativePath}");
                return null;
            }
        }

        return current;
    }

    /// <summary>
    /// 在指定节点下查找文本文件
    /// </summary>
    public static TextFile FindTextFile(FolderNode node, string fileNameWithoutExt)
    {
        if (node == null) return null;
        return node.textFiles.Find(f => f.fileNameWithoutExtension == fileNameWithoutExt);
    }


    /// <summary>
    /// 在指定节点下查找图片文件
    /// </summary>
    public ImageFile FindImageFile(FolderNode node, string fileNameWithoutExt)
    {
        if (node == null) return null;
        return node.imageFiles.Find(f => f.fileNameWithoutExtension == fileNameWithoutExt);
    }

    /// <summary>
    /// 获取所有符合条件的节点(深度搜索)
    /// </summary>
    public List<FolderNode> FindAllFoldersWithName(string folderName)
    {
        List<FolderNode> results = new List<FolderNode>();
        SearchRecursive(rootNode, folderName, results);
        return results;
    }

    void SearchRecursive(FolderNode node, string targetName, List<FolderNode> results)
    {
        if (node.folderName == targetName)
        {
            results.Add(node);
        }

        foreach (var child in node.subFolders)
        {
            SearchRecursive(child, targetName, results);
        }
    }

    // ==================== 使用示例 ====================

    void ExampleUsage()
    {
        if (rootNode == null) return;

        Debug.Log("\n=== 使用示例 ===");

        // 示例1: 遍历根目录下的所有子文件夹
        Debug.Log($"\n根目录下有 {rootNode.subFolders.Count} 个子文件夹:");
        foreach (var folder in rootNode.subFolders)
        {
            Debug.Log($"  - {folder.folderName}");
        }

        // 示例2: 查找特定路径的文件夹
        FolderNode targetFolder = FindFolder("Panel1/Items");
        if (targetFolder != null)
        {
            Debug.Log($"\n找到文件夹: {targetFolder.folderName}");
            Debug.Log($"  包含 {targetFolder.textFiles.Count} 个文本文件");
            Debug.Log($"  包含 {targetFolder.imageFiles.Count} 个图片");
        }

        // 示例3: 读取特定文本文件
        if (rootNode.subFolders.Count > 0)
        {
            var firstFolder = rootNode.subFolders[0];
            var nameFile = FindTextFile(firstFolder, "name");
            if (nameFile != null)
            {
                Debug.Log($"\n读取到文本: {nameFile.fileNameWithoutExtension} = {nameFile.content}");
            }
        }

        // 示例4: 查找所有名为 "Items" 的文件夹
        var itemsFolders = FindAllFoldersWithName("Items");
        Debug.Log($"\n找到 {itemsFolders.Count} 个名为 'Items' 的文件夹");
    }
}
相关推荐
lrh30255 小时前
Custom SRP - 15 Particles
unity·渲染管线·粒子·srp·扰动效果
张人玉5 小时前
C#通信精讲系列——C# 通讯编程基础(含代码实例)
开发语言·c#·c#通信
小熊熊知识库5 小时前
C# Ollama 实战聊天小案例实现
开发语言·c#
arron88995 小时前
WebApi 部署到win7 IIS详细步骤
c#
零点零一5 小时前
C# 的 out 参数:全面解析与最佳实践
c#
c#上位机6 小时前
halcon获取区域中心坐标以及面积——area_center
图像处理·计算机视觉·c#·halcon
Scout-leaf6 小时前
WPF新手村教程(一) - 走不出新手村别找我
c#·wpf
璞瑜无文6 小时前
Unity 游戏开发之布局(二)
unity·c#·游戏引擎
用户8356290780517 小时前
C# 实现 XML 转 Excel:从解析到生成 XLSX 的详细步骤
后端·c#