340 lines
14 KiB
C#
340 lines
14 KiB
C#
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
|
||
{
|
||
|
||
/// <summary>
|
||
/// 获取指定路径下的所有xml文件
|
||
/// </summary>
|
||
/// <param name="paths">文件夹路径</param>
|
||
/// <returns></returns>
|
||
public static List<string> GetXmlFilePathsFromPaths(string[] paths)
|
||
{
|
||
var xmlFilePaths = new List<string>();
|
||
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从指定路径加载所有 XML 文件并解析为 XDocument 对象。
|
||
/// </summary>
|
||
/// <param name="paths">文件夹路径数组。</param>
|
||
/// <returns>包含所有解析后的 XDocument 对象的列表。</returns>
|
||
public static List<XDocument> LoadXmlFromPaths(string[] paths)
|
||
{
|
||
var xDocuments = new List<XDocument>();
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取指定单个路径下的所有 XML 文件。
|
||
/// </summary>
|
||
/// <param name="path">文件夹路径。</param>
|
||
/// <returns>包含所有 XML 文件路径的列表。</returns>
|
||
public static List<string> GetXmlFilePathsFromPath(string path)
|
||
{
|
||
return GetXmlFilePathsFromPaths(new[] { path });
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从指定单个路径加载所有 XML 文件并解析为 XDocument 对象。
|
||
/// </summary>
|
||
/// <param name="path">文件夹路径。</param>
|
||
/// <returns>包含所有解析后的 XDocument 对象的列表。</returns>
|
||
public static List<XDocument> LoadXmlFromPath(string path)
|
||
{
|
||
return LoadXmlFromPaths(new[] { path });
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取文件夹列表中所有直接子文件夹的路径。
|
||
/// </summary>
|
||
/// <param name="folderPaths">文件夹路径列表。</param>
|
||
/// <returns>包含所有子文件夹路径的列表。</returns>
|
||
public static List<string> GetSubFolders(List<string> folderPaths)
|
||
{
|
||
var result = new List<string>();
|
||
|
||
foreach (var folderPath in folderPaths)
|
||
if (Directory.Exists(folderPath))
|
||
{
|
||
// 获取当前文件夹的直接子文件夹
|
||
var subFolders = Directory.GetDirectories(folderPath);
|
||
|
||
// 将子文件夹路径添加到结果列表中
|
||
result.AddRange(subFolders);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning($"警告: 文件夹不存在 - {folderPath}");
|
||
}
|
||
|
||
return result;
|
||
}
|
||
/// <summary>
|
||
/// 用于加载指定路径下的所有资源,并返回资源名称和加载好的资源的键值对。
|
||
/// </summary>
|
||
/// <typeparam name="T">资源类型</typeparam>
|
||
/// <param name="path">资源路径(相对于 Resources 文件夹)</param>
|
||
/// <returns>字典,键为资源名称,值为加载好的资源</returns>
|
||
public static Dictionary<string, T> LoadResources<T>(string path) where T : UnityEngine.Object
|
||
{
|
||
// 创建一个字典来存储资源名称和加载好的资源
|
||
var resourceDict = new Dictionary<string, T>();
|
||
|
||
// 加载指定路径下的所有资源
|
||
var resources = Resources.LoadAll<T>(path);
|
||
|
||
foreach (var resource in resources)
|
||
{
|
||
if (resource != null)
|
||
{
|
||
// 获取资源名称并存入字典
|
||
var resourceName = resource.name;
|
||
resourceDict[resourceName] = resource;
|
||
}
|
||
}
|
||
|
||
return resourceDict;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从外部指定文件中加载图片
|
||
/// </summary>
|
||
/// <param name="filePath">图片文件的完整路径</param>
|
||
/// <returns>加载成功的 Texture2D 对象,或加载失败时返回 null</returns>
|
||
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;
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 获取指定目录下所有匹配后缀名的文件路径(可递归)
|
||
/// </summary>
|
||
/// <param name="directoryPath">目标文件夹路径</param>
|
||
/// <param name="extensions">后缀名列表(如 ["txt", "jpg"])</param>
|
||
/// <param name="searchOption">是否包含子文件夹</param>
|
||
/// <returns>匹配的文件路径列表</returns>
|
||
public static List<string> 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<string>(
|
||
extensions.Select(ext => ext.TrimStart('.').ToLower())
|
||
);
|
||
|
||
var result = new List<string>();
|
||
|
||
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;
|
||
}
|
||
/// <summary>
|
||
/// 根据文件路径推断音频类型。
|
||
/// </summary>
|
||
/// <param name="filePath">音频文件的完整路径。</param>
|
||
/// <returns>推断出的 AudioType,如果无法推断则返回 AudioType.UNKNOWN。</returns>
|
||
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尝试自动检测,但成功率可能不如指定类型高
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 从外部指定文件中异步加载音频。
|
||
/// 注意:此方法是异步的,需要使用 await 调用。在Unity主线程中调用以避免潜在的线程问题。
|
||
/// </summary>
|
||
/// <param name="filePath">音频文件的完整路径。</param>
|
||
/// <returns>Task,其结果为加载成功的 AudioClip 对象,或加载失败时返回 null。</returns>
|
||
public static async Task<AudioClip> 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;
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|