using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; public class TextureLoadHelp : MonoBehaviour { public static TextureLoadHelp _Instance; private Dictionary tempTexList; private Dictionary waitLoadImgActionList; private Dictionary waitLoadImgActionList_RawImg; public float currentTotalSize = 0; public float maxSize = 500; //图片缓存-m private Dictionary loadDoneABList; private Dictionary loadingABList; public Texture map_def; //临时存的封面图 public Texture[] tempTextures; public string[] tempTextureName; public Texture GetTempTexture(string name) { int index = -1; for (int i = 0; i < tempTextureName.Length; i++) { if (tempTextureName[i].Equals(name)) { index = i; break; } } if (index != -1) { return tempTextures[index]; } else { return null; } } private void Awake() { _Instance = this; tempTexList = new Dictionary(); waitLoadImgActionList = new Dictionary(); waitLoadImgActionList_RawImg = new Dictionary(); loadDoneABList = new Dictionary(); loadingABList = new Dictionary(); } /// /// 加载图片 /// /// /// /// public long LoadTexFromUrl(string path, RawImage rawImg) { long loadId = GetDownId(); //Debug.Log("下载图片:"+loadId); // if (CheckCache(path)) // { // rawImg.texture = LoadFromCache(path); // return 0; // } if (tempTexList.TryGetValue(path, out var value)) { value.isUsing = true; rawImg.texture = value.tex; loadId = 0; } else { waitLoadImgActionList_RawImg.Add(loadId, rawImg); StartCoroutine(DownLoadTex_Raw(path, loadId)); } return loadId; } public long LoadTexFromUrl_AB(string ab_Name, string FileName, Material mat) { if (tempTexList.TryGetValue(FileName, out var value)) { value.isUsing = true; mat.mainTexture = value.tex; return 0; } mat.mainTexture = map_def; long loadId = GetDownId(); waitLoadImgActionList.Add(loadId, mat); StartCoroutine(DownLoadTex_AB(ab_Name, FileName, loadId)); return loadId; } /// /// 取消加载 /// /// public void CancelLoad(long loadId) { if (waitLoadImgActionList.ContainsKey(loadId)) { waitLoadImgActionList.Remove(loadId); } } /// /// 标记缓存图片为未使用 /// /// public void UnUsingTex(string path) { if (tempTexList.TryGetValue(path, out TempTexData disposeData)) { disposeData.isUsing = false; } else { Debug.Log($"不存在缓存:{path}"); } } IEnumerator DownLoadTex_AB(string ab_Name, string fileName, long loadId) { if (loadingABList.ContainsKey(ab_Name)) { //Debug.Log($"{ab_Name} downloading...wait"); yield return new WaitUntil(() => loadingABList[ab_Name] > 0); // if (loadingABList.ContainsKey(ab_Name)) // { // loadingABList.Remove(ab_Name); // } } AssetBundle tempAb; Texture2D tex; if (loadDoneABList.TryGetValue(ab_Name, out var value)) { tempAb = value; tex = tempAb.LoadAsset(fileName); if (waitLoadImgActionList.TryGetValue(loadId, out Material targetMat)) { if (targetMat != null && tex != null) { targetMat.mainTexture = tex; } else { if (targetMat == null) { Debug.Log($"{fileName} 材质球不存在"); } if (tex == null) { Debug.Log($"{fileName} 图片不存在"); } } waitLoadImgActionList.Remove(loadId); } } else { //添加到正在下载 loadingABList.TryAdd(ab_Name, 0); #if UNITY_EDITOR WWW www = new WWW($"{Application.streamingAssetsPath}/{ab_Name}"); #else WWW www = WWW.LoadFromCacheOrDownload($"{Application.streamingAssetsPath}/{ab_Name}",0); #endif yield return www; if (www.isDone) { tempAb = www.assetBundle; loadDoneABList.Add(ab_Name, tempAb); loadingABList[ab_Name] = 1; tex = tempAb.LoadAsset(fileName); tempTexList.TryAdd(fileName, new TempTexData() { loadTime = GetTimeStamp(), name = fileName, tex = tex, size = 0, isUsing = true }); if (waitLoadImgActionList.TryGetValue(loadId, out Material targetMat)) { if (targetMat != null && tex != null) { targetMat.mainTexture = tex; } else { if (targetMat == null) { Debug.Log($"{fileName} 材质球不存在"); } if (tex == null) { Debug.Log($"{fileName} 图片不存在"); } } waitLoadImgActionList.Remove(loadId); } } else { loadingABList[ab_Name] = 2; Debug.LogError($"{ab_Name}下载失败:{www.error}"); } www.Dispose(); } } IEnumerator DownLoadTex(string path, long loadId) { UnityWebRequest www = UnityWebRequestTexture.GetTexture(path); yield return www.SendWebRequest(); if (www.downloadHandler.isDone) { if (waitLoadImgActionList.ContainsKey(loadId)) { var texture = ((DownloadHandlerTexture)www.downloadHandler).texture; float tempSize = GetSize_m(www.downloadedBytes); tempTexList.TryAdd(path, new TempTexData() { loadTime = GetTimeStamp(), name = path, tex = texture, size = tempSize, isUsing = true }); currentTotalSize += tempSize; CheckSize(); if (waitLoadImgActionList.TryGetValue(loadId, out Material targetMat)) { if (targetMat != null) { targetMat.mainTexture = texture; } waitLoadImgActionList.Remove(loadId); } SaveInCache(path, www.downloadHandler.data); } else { www.disposeDownloadHandlerOnDispose = true; Debug.Log(path + " 下载已取消"); } } else { Debug.LogError($"{path}下载失败:{www.downloadHandler.error}"); } www.Dispose(); } IEnumerator DownLoadTex_Raw(string path, long loadId) { WWW www = new WWW(path); yield return www; if (www.isDone) { if (waitLoadImgActionList_RawImg.ContainsKey(loadId)) { var texture = www.texture; float tempSize = GetSize_m((ulong)www.bytesDownloaded); tempTexList.TryAdd(path, new TempTexData() { loadTime = GetTimeStamp(), name = path, tex = texture, size = tempSize, isUsing = true }); currentTotalSize += tempSize; CheckSize(); if (waitLoadImgActionList_RawImg.TryGetValue(loadId, out RawImage rawImage)) { if (rawImage != null) { rawImage.texture = texture; } waitLoadImgActionList_RawImg.Remove(loadId); } } else { Debug.Log(path + " 下载已取消"); } } else { Debug.LogError($"{path}下载失败:{www.error}"); } www.Dispose(); } private void SaveInCache(string url, byte[] data) { string fileName = Path.GetFileName(url); string path = Application.persistentDataPath; File.WriteAllBytes(path + fileName, data); Debug.Log($"缓存:{path}{fileName}"); } private Texture2D LoadFromCache(string url) { string fileName = Path.GetFileName(url); string path = Application.persistentDataPath; byte[] texBytes = File.ReadAllBytes(path + fileName); currentTotalSize += GetSize_m((ulong)texBytes.Length); Texture2D tempTex = new Texture2D(2, 2); tempTex.LoadImage(texBytes); tempTex.Apply(); return tempTex; } // private bool CheckCache(string url) // { // string fileName = Path.GetFileName(url); // string path = Application.persistentDataPath; // //Debug.Log($"CaChe:{path}"); // return File.Exists(path + fileName); // } public void CheckSize() { if (currentTotalSize >= maxSize) { List values = tempTexList.Values.ToList(); values.Sort(); for (int i = 0; i < values.Count; i++) { if (!values[i].isUsing) { if (tempTexList.TryGetValue(values[i].name, out TempTexData disposeData)) { disposeData.tex = null; currentTotalSize -= disposeData.size; tempTexList.Remove(disposeData.name); } } if (currentTotalSize < maxSize) { break; } } if (currentTotalSize >= maxSize) { Debug.Log($"临时图片已超过限制大小且无可释放项!!!:{currentTotalSize}/{maxSize}"); } } } /// /// 清空全部缓存 /// public void ClearAllTempTex() { List values = tempTexList.Values.ToList(); for (int i = 0; i < values.Count; i++) { if (tempTexList.TryGetValue(values[i].name, out TempTexData disposeData)) { disposeData.tex = null; currentTotalSize -= disposeData.size; tempTexList.Remove(disposeData.name); } } waitLoadImgActionList.Clear(); tempTexList.Clear(); Resources.UnloadUnusedAssets(); GC.Collect(); } private long GetDownId() { long id = ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000); while (waitLoadImgActionList.ContainsKey(id)) { id++; } return id; } private long GetTimeStamp() { return (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000; } private float GetSize_m(ulong size_b) { return (size_b * 1.0f / (1024.0f * 1024.0f)); } } public class TempTexData : IComparable { public string name; public Texture tex; public long loadTime; public float size; public bool isUsing = true; public int CompareTo(TempTexData other) { if (other.loadTime < loadTime) { return 1; } if (other.loadTime == loadTime) { return 0; } return -1; } }