Files
Gen_Hack-and-Slash-Roguelite/Client/Assets/Scripts/Configs/ConfigProcessor.cs

340 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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); // 初始大小为 2x2LoadImage 会自动调整大小
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;
}
}
}
}
}