using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace TcgEngine
{
///
/// 动态Sprite加载器,支持从本地下载的资源中加载图片
///
public class SpriteLoader : MonoBehaviour
{
private static SpriteLoader instance;
private Dictionary spriteCache = new Dictionary();
private Dictionary textureCache = new Dictionary();
public static SpriteLoader Instance
{
get
{
if (instance == null)
{
GameObject go = new GameObject("SpriteLoader");
instance = go.AddComponent();
DontDestroyOnLoad(go);
}
return instance;
}
}
private void Awake()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject);
}
else if (instance != this)
{
Destroy(gameObject);
}
}
///
/// 从本地文件加载Sprite
///
/// 相对于Sprites文件夹的路径
/// 加载的Sprite,失败返回null
public Sprite LoadSprite(string relativePath)
{
if (string.IsNullOrEmpty(relativePath))
{
Debug.LogWarning("[SpriteLoader] Empty relativePath provided");
return null;
}
Debug.Log($"[SpriteLoader] Loading sprite: {relativePath}");
// 检查缓存
if (spriteCache.ContainsKey(relativePath))
{
Debug.Log($"[SpriteLoader] Found in cache: {relativePath}");
return spriteCache[relativePath];
}
try
{
// 先尝试从下载的本地资源加载
string localPath = GetLocalSpritePath(relativePath);
Debug.Log($"[SpriteLoader] Checking local path: {localPath}");
if (File.Exists(localPath))
{
Debug.Log($"[SpriteLoader] Local file exists, loading from: {localPath}");
Sprite sprite = LoadSpriteFromFile(localPath);
if (sprite != null)
{
Debug.Log($"[SpriteLoader] Successfully loaded from local file: {relativePath}");
spriteCache[relativePath] = sprite;
return sprite;
}
else
{
Debug.LogWarning($"[SpriteLoader] Failed to load sprite from local file: {localPath}");
}
}
else
{
Debug.LogWarning($"[SpriteLoader] Local file does not exist: {localPath}");
}
// 如果本地文件不存在,尝试从Resources加载(fallback)
Debug.Log($"[SpriteLoader] Trying Resources fallback for: {relativePath}");
Sprite fallbackSprite = LoadSpriteFromResources(relativePath);
if (fallbackSprite != null)
{
Debug.Log($"[SpriteLoader] Successfully loaded from Resources: {relativePath}");
spriteCache[relativePath] = fallbackSprite;
return fallbackSprite;
}
Debug.LogWarning($"[SpriteLoader] Failed to load sprite from both local and Resources: {relativePath}");
return null;
}
catch (Exception e)
{
Debug.LogError($"[SpriteLoader] Error loading sprite {relativePath}: {e.Message}");
return null;
}
}
///
/// 从文件系统加载Sprite
///
private Sprite LoadSpriteFromFile(string filePath)
{
try
{
// 加载纹理
Texture2D texture = LoadTextureFromFile(filePath);
if (texture == null)
return null;
// 创建Sprite
Sprite sprite = Sprite.Create(
texture,
new Rect(0, 0, texture.width, texture.height),
new Vector2(0.5f, 0.5f)
);
return sprite;
}
catch (Exception e)
{
Debug.LogError($"Error loading sprite from file {filePath}: {e.Message}");
return null;
}
}
///
/// 从文件加载纹理
///
private Texture2D LoadTextureFromFile(string filePath)
{
if (textureCache.ContainsKey(filePath))
{
return textureCache[filePath];
}
try
{
byte[] fileData = File.ReadAllBytes(filePath);
Texture2D texture = new Texture2D(2, 2);
if (texture.LoadImage(fileData))
{
textureCache[filePath] = texture;
return texture;
}
else
{
Destroy(texture);
return null;
}
}
catch (Exception e)
{
Debug.LogError($"Error loading texture from file {filePath}: {e.Message}");
return null;
}
}
///
/// 从Resources文件夹加载Sprite(fallback)
///
private Sprite LoadSpriteFromResources(string relativePath)
{
try
{
// 移除文件扩展名
string resourcePath = Path.ChangeExtension(relativePath, null);
// 尝试直接加载Sprite
Sprite sprite = Resources.Load(resourcePath);
if (sprite != null)
return sprite;
// 如果直接加载失败,尝试加载Texture2D然后转换
Texture2D texture = Resources.Load(resourcePath);
if (texture != null)
{
return Sprite.Create(
texture,
new Rect(0, 0, texture.width, texture.height),
new Vector2(0.5f, 0.5f)
);
}
return null;
}
catch (Exception e)
{
Debug.LogError($"Error loading sprite from resources {relativePath}: {e.Message}");
return null;
}
}
///
/// 获取本地Sprite文件路径
///
private string GetLocalSpritePath(string relativePath)
{
if (ResourceDownloader.Get() != null)
{
return ResourceDownloader.Get().GetLocalSpritePath(relativePath);
}
// Fallback路径
string basePath = Path.Combine(Application.persistentDataPath, "Sprites");
return Path.Combine(basePath, relativePath);
}
///
/// 清理缓存
///
public void ClearCache()
{
foreach (var sprite in spriteCache.Values)
{
if (sprite != null)
Destroy(sprite);
}
spriteCache.Clear();
foreach (var texture in textureCache.Values)
{
if (texture != null)
Destroy(texture);
}
textureCache.Clear();
}
///
/// 预加载指定目录下的所有图片
///
public void PreloadSprites(string directory)
{
try
{
string localDir = GetLocalSpritePath(directory);
if (!Directory.Exists(localDir))
return;
string[] files = Directory.GetFiles(localDir, "*.png", SearchOption.AllDirectories);
foreach (string file in files)
{
string relativePath = GetRelativePath(file);
LoadSprite(relativePath);
}
}
catch (Exception e)
{
Debug.LogError($"Error preloading sprites from {directory}: {e.Message}");
}
}
///
/// 获取相对路径
///
private string GetRelativePath(string fullPath)
{
string spritesPath = GetLocalSpritePath("");
if (fullPath.StartsWith(spritesPath))
{
return fullPath.Substring(spritesPath.Length + 1);
}
return fullPath;
}
///
/// 检查Sprite是否存在
///
public bool SpriteExists(string relativePath)
{
if (spriteCache.ContainsKey(relativePath))
return true;
string localPath = GetLocalSpritePath(relativePath);
if (File.Exists(localPath))
return true;
// 检查Resources
string resourcePath = Path.ChangeExtension(relativePath, null);
Sprite sprite = Resources.Load(resourcePath);
if (sprite != null)
{
Resources.UnloadAsset(sprite);
return true;
}
Texture2D texture = Resources.Load(resourcePath);
if (texture != null)
{
Resources.UnloadAsset(texture);
return true;
}
return false;
}
private void OnDestroy()
{
ClearCache();
}
public static SpriteLoader Get()
{
return Instance;
}
}
}