using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; // 未在提供代码段中使用,但保留以便与原始上下文保持一致 // 未在提供代码段中使用,但保留以便与原始上下文保持一致 using System.Xml.Linq; // 未在提供代码段中使用,但保留以便与原始上下文保持一致 using UnityEngine; using UnityEngine.Networking; // 未在提供代码段中使用,但保留以便与原始上下文保持一致 // 未在提供代码段中使用,但保留以便与原始上下文保持一致 namespace Configs { public static class ConfigProcessor { /// /// 获取指定路径下的所有xml文件 /// /// 文件夹路径 /// public static List GetXmlFilePathsFromPaths(string[] paths) { var xmlFilePaths = new List(); foreach (var path in paths) { try { // 检查目录是否存在 if (!Directory.Exists(path)) { // **逻辑修改 1.1**: 将静默跳过改为记录警告,提供更友好的提示。 Debug.LogWarning($"警告: 指定路径不存在或无法访问 - {path}"); continue; } // **逻辑修改 1.2**: 原始逻辑仅遍历子文件夹,导致根路径下的XML文件被忽略。 // 现修改为直接获取当前路径及其所有子目录中的 XML 文件。 var xmlFiles = Directory.GetFiles(path, "*.xml", SearchOption.AllDirectories); xmlFilePaths.AddRange(xmlFiles); } catch (Exception ex) { // 优化错误信息,明确是哪个路径出现问题 Debug.LogError($"获取路径 '{path}' 下的XML文件时发生错误: {ex.Message}"); } } return xmlFilePaths; } /// /// 从指定路径加载所有 XML 文件并解析为 XDocument 对象。 /// /// 文件夹路径数组。 /// 包含所有解析后的 XDocument 对象的列表。 public static List LoadXmlFromPaths(string[] paths) { var xDocuments = new List(); var xmlFilePaths = GetXmlFilePathsFromPaths(paths); foreach (var filePath in xmlFilePaths) try { var xDoc = XDocument.Load(filePath); xDocuments.Add(xDoc); } catch (Exception ex) { Debug.LogError($"加载 XML 文件 {filePath} 时发生错误: {ex.Message}"); } return xDocuments; } /// /// 获取指定单个路径下的所有 XML 文件。 /// /// 文件夹路径。 /// 包含所有 XML 文件路径的列表。 public static List GetXmlFilePathsFromPath(string path) { return GetXmlFilePathsFromPaths(new[] { path }); } /// /// 从指定单个路径加载所有 XML 文件并解析为 XDocument 对象。 /// /// 文件夹路径。 /// 包含所有解析后的 XDocument 对象的列表。 public static List LoadXmlFromPath(string path) { return LoadXmlFromPaths(new[] { path }); } /// /// 获取文件夹列表中所有直接子文件夹的路径。 /// /// 文件夹路径列表。 /// 包含所有子文件夹路径的列表。 public static List GetSubFolders(List folderPaths) { var result = new List(); foreach (var folderPath in folderPaths) if (Directory.Exists(folderPath)) { // 获取当前文件夹的直接子文件夹 var subFolders = Directory.GetDirectories(folderPath); // 将子文件夹路径添加到结果列表中 result.AddRange(subFolders); } else { Debug.LogWarning($"警告: 文件夹不存在 - {folderPath}"); } return result; } /// /// 用于加载指定路径下的所有资源,并返回资源名称和加载好的资源的键值对。 /// /// 资源类型 /// 资源路径(相对于 Resources 文件夹) /// 字典,键为资源名称,值为加载好的资源 public static Dictionary LoadResources(string path) where T : UnityEngine.Object { // 创建一个字典来存储资源名称和加载好的资源 var resourceDict = new Dictionary(); // 加载指定路径下的所有资源 var resources = Resources.LoadAll(path); foreach (var resource in resources) { if (resource != null) { // 获取资源名称并存入字典 var resourceName = resource.name; resourceDict[resourceName] = resource; } } return resourceDict; } /// /// 从外部指定文件中加载图片 /// /// 图片文件的完整路径 /// 加载成功的 Texture2D 对象,或加载失败时返回 null public static Texture2D LoadTextureByIO(string filePath) { if (string.IsNullOrEmpty(filePath)) { Debug.LogError("文件路径为空,请检查输入!"); return null; } // 检查文件是否存在 if (!File.Exists(filePath)) { Debug.LogError($"文件不存在: {filePath}"); return null; } byte[] bytes; try { // 使用 using 自动管理 FileStream 的生命周期 using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { bytes = new byte[fs.Length]; // 创建一个字节数组来存储文件内容 fs.Read(bytes, 0, bytes.Length); // 读取文件内容到字节数组 } } catch (Exception e) { Debug.LogError($"读取文件时发生错误: {e.Message}"); return null; } // 创建一个默认大小的 Texture2D 对象 var texture = new Texture2D(2, 2, TextureFormat.RGBA32, false); // 初始大小为 2x2,LoadImage 会自动调整大小 if (texture.LoadImage(bytes)) // 加载图片数据 { // 设置过滤模式为 Point (无插值) texture.filterMode = FilterMode.Point; texture.wrapMode = TextureWrapMode.Clamp; // 防止边缘出现意外拉伸 return texture; // 返回加载成功的 Texture2D 对象 } else { Debug.LogError("图片加载失败,请检查文件格式是否正确!"); return null; } } /// /// 获取指定目录下所有匹配后缀名的文件路径(可递归) /// /// 目标文件夹路径 /// 后缀名列表(如 ["txt", "jpg"]) /// 是否包含子文件夹 /// 匹配的文件路径列表 public static List GetFilesByExtensions( string directoryPath, string[] extensions, SearchOption searchOption = SearchOption.AllDirectories) { if (string.IsNullOrWhiteSpace(directoryPath)) throw new ArgumentException("目录路径不能为空", nameof(directoryPath)); if (!Directory.Exists(directoryPath)) throw new DirectoryNotFoundException($"目录不存在: {directoryPath}"); if (extensions == null || extensions.Length == 0) throw new ArgumentException("后缀名列表不能为空", nameof(extensions)); // 标准化后缀名(去掉点,转小写) var normalizedExtensions = new HashSet( extensions.Select(ext => ext.TrimStart('.').ToLower()) ); var result = new List(); try { var files = Directory.GetFiles(directoryPath, "*", searchOption); foreach (var file in files) { var ext = Path.GetExtension(file).TrimStart('.').ToLower(); if (normalizedExtensions.Contains(ext)) { result.Add(file); } } } catch (UnauthorizedAccessException ex) { // **逻辑修改 3**: 在 Unity 环境中,应使用 Debug.LogError 而非 Console.WriteLine 记录错误。 Debug.LogError($"访问目录 '{directoryPath}' 被拒绝: {ex.Message}"); } return result; } /// /// 根据文件路径推断音频类型。 /// /// 音频文件的完整路径。 /// 推断出的 AudioType,如果无法推断则返回 AudioType.UNKNOWN。 private static AudioType GetAudioTypeFromFilePath(string filePath) { string ext = Path.GetExtension(filePath)?.ToLower(); // 获取扩展名并转小写 switch (ext) { case ".wav": return AudioType.WAV; case ".mp3": return AudioType.MPEG; case ".ogg": return AudioType.OGGVORBIS; case ".aiff": return AudioType.AIFF; // 可以根据需要添加更多常见的音频类型 default: Debug.LogWarning($"警告: 未知音频文件类型 '{ext}' for file '{filePath}'. 尝试使用 AudioType.UNKNOWN."); return AudioType.UNKNOWN; // 让Unity尝试自动检测,但成功率可能不如指定类型高 } } /// /// 从外部指定文件中异步加载音频。 /// 注意:此方法是异步的,需要使用 await 调用。在Unity主线程中调用以避免潜在的线程问题。 /// /// 音频文件的完整路径。 /// Task,其结果为加载成功的 AudioClip 对象,或加载失败时返回 null。 public static async Task LoadAudioByIO(string filePath) { if (string.IsNullOrEmpty(filePath)) { Debug.LogError("音频文件路径为空,请检查输入!"); return null; } if (!File.Exists(filePath)) { Debug.LogError($"音频文件不存在: {filePath}"); return null; } // UnityWebRequest需要使用file://协议来访问本地文件 string uri = "file://" + Path.GetFullPath(filePath); // 根据文件扩展名推断音频类型 AudioType audioType = GetAudioTypeFromFilePath(filePath); using (UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(uri, audioType)) { try { // 发送请求并等待完成 // await www.SendWebRequest(); 是核心,它会异步执行网络请求。 // 如果在Unity Editor中遇到“You are trying to load data from a www stream that had a non-OK status”等错误, // 可以检查文件路径和文件权限。 await www.SendWebRequest(); // 检查请求结果 // www.isNetworkError 或 www.isHttpError 在较新的Unity版本中已弃用, // 推荐使用 www.result。 if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError) { Debug.LogError($"加载音频文件 '{filePath}' 失败: {www.error}"); return null; } else { // 获取下载的AudioClip AudioClip clip = DownloadHandlerAudioClip.GetContent(www); if (clip == null) { Debug.LogError($"未能从文件 '{filePath}' 获取 AudioClip 内容,请检查文件是否损坏或格式是否支持 ({audioType} 类型)."); } return clip; } } catch (Exception e) { Debug.LogError($"处理音频文件 '{filePath}' 时发生异常: {e.Message}"); return null; } } } } }