#if UNITY_EDITOR using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Runtime.Serialization; using LuaFramework; using LuaInterface; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.Video; public class ResourceManagerEx : ILocalResLoader { ResourceManager mgr; FilePathRuleInfo pathRules; Dictionary resLoadedTime; Dictionary cachePaths; string rulePath = Application.dataPath + "/FilePathRule.json"; string cacheFilePath = Application.dataPath + "/FilePathCache.txt"; public void Init(ResourceManager mgr) { this.mgr = mgr; resLoadedTime = new Dictionary(); if (File.Exists(rulePath)) { var infoContent = File.ReadAllText(rulePath); pathRules = JsonUtility.FromJson(infoContent); } if (AppConst.IsUseLocalPathCache) { cachePaths = new Dictionary(); if (File.Exists(cacheFilePath)) { var infoContent = File.ReadAllLines(cacheFilePath); foreach (var item in infoContent) { var kvParts = item.Split(','); cachePaths.Add(kvParts[0], kvParts[1]); } } } } public void OnDestroy() { if (AppConst.IsUseLocalPathCache) { List cacheList = new List(); foreach (var item in cachePaths) { cacheList.Add(item.Key+","+item.Value); } File.WriteAllLines(cacheFilePath, cacheList.ToArray()); } } public bool Load(string abName, string[] assetNames, Type type, Action action = null, LuaFunction func = null, uint level = 0) { if (assetNames.Length==0) return false; if (abName.EndsWith(AppConst.ExtName)) abName = abName.Substring(0, abName.Length-AppConst.ExtName.Length); assetNames = HandleMultipleRes(assetNames); if (assetNames.Length > 1) { //同时加载多个文件 LoadMultipleAssetsInLocal(abName, assetNames, type, action, func, level); return true; } var filePath = GetRealPath(abName, assetNames[0], type); if (filePath == "") return false; mgr.StartCoroutine(LoadAssetInLocal(filePath, abName, assetNames[0], type, action, func)); return true; } IEnumerator LoadAssetInLocal(string filePath, string abName, string resName, Type type, Action action = null, LuaFunction func = null) { //如果之前已经加载过的话就不用等到下一帧才加载成功 var hasLoaded = resLoadedTime.ContainsKey(filePath.ToLowerInvariant()); if (!hasLoaded) yield return new WaitForSeconds(0.01f); UnityEngine.Object res = UnityEditor.AssetDatabase.LoadAssetAtPath(filePath, type); if (res != null) { if (resLoadedTime.ContainsKey(filePath.ToLowerInvariant())) resLoadedTime[filePath.ToLowerInvariant()] = Time.time; else resLoadedTime.Add(filePath.ToLowerInvariant(), Time.time); if (func != null) { List list = new List(); list.Add(res); object[] args = new object[] { list.ToArray() }; func.Call(args); func.Dispose(); func = null; } else if (action != null) { List list = new List(); list.Add(res); UnityEngine.Object[] args = list.ToArray(); action(args); } } else { Debug.Log("ResourceManagerEx:LoadAssetInLocal Error:cannot find file:" + filePath+" ab:"+abName+" res:"+resName); } yield return null; } void LoadMultipleAssetsInLocal(string abName, string[] assetNames, Type type, Action action = null, LuaFunction func = null, uint level = 0) { List list = new List(); foreach (var resName in assetNames) { var filePath = GetRealPath(abName, resName, type); UnityEngine.Object res = UnityEditor.AssetDatabase.LoadAssetAtPath(filePath, type); // Debug.Log("LoadMultipleAssetsInLocal res : "+(res!=null)+" file:"+filePath+" ab:"+abName+" res:"+resName); list.Add(res);//不管是否为null都要放进去 if (res != null) { if (resLoadedTime.ContainsKey(filePath.ToLowerInvariant())) resLoadedTime[filePath.ToLowerInvariant()] = Time.time; else resLoadedTime.Add(filePath.ToLowerInvariant(), Time.time); } else { Debug.Log("ResourceManagerEx:LoadMultipleAssetsInLocal Error:cannot find file:" + filePath+" ab:"+abName+" res:"+resName); } } if (func != null) { object[] args = new object[] { list.ToArray() }; func.Call(args); func.Dispose(); func = null; } else if (action != null) { UnityEngine.Object[] args = list.ToArray(); action(args); } } //因为传入的assetNames可能是{"1.png,2.png","3.png","4.png"},注意1和2是连在一起的,所以需要转化为单独元素的列表:{"1.png","2.png","3.png","4.png"} string[] HandleMultipleRes(string[] assetNames) { var hasMultiResInOne = false; foreach (var names in assetNames) { if (names.IndexOf(',')!=-1) { hasMultiResInOne = true; break; } } if (hasMultiResInOne) { List realResList = new List(); foreach (var names in assetNames) { if (names.IndexOf(',')!=-1) { var parts = names.Split(','); foreach (var part in parts) { realResList.Add(part); } } else { realResList.Add(names); } } assetNames = realResList.ToArray(); } return assetNames; } private static string GetIconFilePathInDeep(string path, string[] abNames, string spriteName) { if (System.IO.Directory.Exists(path)) { System.IO.DirectoryInfo direction = new System.IO.DirectoryInfo(path); System.IO.DirectoryInfo[] sub_directions = direction.GetDirectories(); foreach (var dir in sub_directions) { string try_dir_path = path + dir.Name + "/"; string result = try_dir_path + spriteName; if (dir.Name == abNames[1]) { System.IO.DirectoryInfo try_dir = new System.IO.DirectoryInfo(try_dir_path); System.IO.FileInfo[] files = try_dir.GetFiles("*", System.IO.SearchOption.AllDirectories); for (int i = 0; i < files.Length; i++) { if (files[i].Name == (spriteName)) { path = files[i].FullName; return path; } } } else { result = GetIconFilePathInDeep(try_dir_path, abNames, spriteName); if (result != "") return result; } } } return ""; } static List NoTextureFolder = new List { "alphasingle", "alphaCommon", "alphaMain" }; private string GetRealPath(string abName, string resName, Type type) { string path = ""; do { var cacheKey = (abName+":"+resName).ToLowerInvariant(); // Debug.Log("cachePaths.ContainsKey(cacheKey) : "+cachePaths.ContainsKey(cacheKey)+" key:"+cacheKey); if (AppConst.IsUseLocalPathCache && cachePaths.ContainsKey(cacheKey)) { path = cachePaths[cacheKey]; break; } var dotIndex = resName.IndexOf('.'); if (dotIndex != -1) resName = resName.Substring(0, dotIndex); path = SearchInUI(abName, resName); if (path != "") break; path = SearchByRules(abName, resName); if (path != "") break; path = SearchInIcon(abName, resName); if (path != "") break; if (AppConst.UseLocalResource >= 2) { //这一步将从整个项目资源目录进行搜索,会很卡的,建议发现找不到资源时在FilePathRule.json文件增加搜索规则 path = SearchInAll(abName, resName, type); if (path != "") break; } } while (false); var isFileExist = File.Exists(path); // Debug.Log("load local file failed : "+"isFileExist: "+isFileExist+" abName:"+abName+" res:"+assetNames[0]+" guess file:"+filePath); if (!isFileExist) { if (AppConst.PrintLoadLocalRes >= 1) { var isPrintStack = AppConst.PrintLoadLocalRes >= 2; string printContent = "load local file failed : "+"abName:"+abName+" res:"+resName+" guess file:"+path; if (isPrintStack) printContent += new System.Diagnostics.StackTrace().ToString(); Debug.Log(printContent); } path = ""; } if (path.IndexOf(':')!=-1) { path = path.Replace('\\', '/'); path = UnityEditor.FileUtil.GetProjectRelativePath(path); } if (AppConst.IsUseLocalPathCache) { if (File.Exists(path)) { var cacheKey = (abName+":"+resName).ToLowerInvariant(); // if (cachePaths.ContainsKey(cacheKey)) cachePaths[cacheKey] = path; // else // cachePaths.Add(cacheKey, path); } } return path; } private string SearchByRules(string abName, string resName) { foreach (var rule in pathRules.Rules) { if (rule.Type == "StartsWith") { if (abName.StartsWith(rule.Key)) { foreach (var testPath in rule.Paths) { var realPath = string.Format(testPath, resName); if (File.Exists(realPath)) return realPath; } } } } return ""; } private string SearchInAll(string abName, string resName, Type type) { string typeName = GetTypeName(type); string findFilter = resName; if (typeName != "") findFilter += " t:" + typeName; string[] guids = UnityEditor.AssetDatabase.FindAssets(findFilter); var retNum = guids.Length; // Debug.Log(" findFilter : "+findFilter+" retNum:"+retNum+" typeName:"+typeName); if (retNum == 1) { return UnityEditor.AssetDatabase.GUIDToAssetPath(guids[0]); } if (retNum > 1) { foreach (var retPathUID in guids) { var retPath = UnityEditor.AssetDatabase.GUIDToAssetPath(retPathUID); // Debug.Log(retPath+" isEndWith:"+retPath.EndsWith(resName+"."+typeName.ToLowerInvariant())); var fileSubffix = GetTypeFileSubffix(type); if (retPath.ToLowerInvariant().EndsWith((resName+fileSubffix).ToLowerInvariant())) return retPath; } } return ""; } private string GetTypeName(Type type) { if (type == typeof(GameObject)) return "Prefab"; else if (type == typeof(Sprite)) return "Sprite"; else if (type == typeof(Texture)) return "Texture"; else if (type == typeof(Mesh)) return "Mesh"; else if (type == typeof(Shader)) return "Shader"; else if (type == typeof(Scene)) return "Scene"; else if (type == typeof(Font)) return "Font"; else if (type == typeof(Material)) return "Material"; else if (type == typeof(AudioClip)) return "AudioClip"; return ""; } private string GetTypeFileSubffix(Type type) { if (type == typeof(GameObject)) return ".prefab"; else if (type == typeof(Sprite)) return ".png"; else if (type == typeof(Texture)) return ".jpg"; else if (type == typeof(Mesh)) return ".fbx"; else if (type == typeof(Shader)) return ".shader"; else if (type == typeof(Scene)) return ".scene"; else if (type == typeof(Font)) return ".fnt"; else if (type == typeof(Material)) return ".mat"; else if (type == typeof(AudioClip)) return ".ogg"; return ""; } private string SearchInIcon(string abName, string resName) { if (abName.StartsWith("icon_")) { string[] path_fix = abName.Split('_'); if (path_fix.Length >= 2) { string try_path = "Assets/LuaFramework/AssetBundleRes/iconjpg/" + resName; if (!resName.EndsWith("jpg")) try_path += ".jpg"; //Debug.Log("iconjpg try_path : "+try_path); if (File.Exists(try_path)) { return try_path; } else { string folder_str = path_fix[1]; try_path = "Assets/LuaFramework/AssetBundleRes/icon/" + folder_str + "/" + resName; if (!resName.EndsWith(".png")) resName += ".png"; //Debug.Log("icon try_path : "+try_path); if (File.Exists(try_path)) { return try_path; } else { try_path = "Assets/LuaFramework/AssetBundleRes/icon/" + folder_str + "/necessaryBg/" + resName; if (!resName.EndsWith(".png")) resName += ".png"; if (File.Exists(try_path)) { return try_path; } else { try_path = GetIconFilePathInDeep("Assets/LuaFramework/AssetBundleRes/icon/", path_fix, resName); if (try_path != "") { if (try_path.IndexOf(':') != -1) try_path = UnityEditor.FileUtil.GetProjectRelativePath(try_path); return try_path; } } } } } } return ""; } private string SearchInUI(string abName, string resName) { string path = ""; bool is_no_texture_folder = false; foreach (var item in NoTextureFolder) { if (abName.StartsWith(item)) { is_no_texture_folder = true; path = "Assets/LuaFramework/AssetBundleRes/ui/" + item + "/" + resName + ".png"; //Debug.Log("NoTextureFolder abName:"+abName+" resName:"+resName+" path:"+path); return path; } } if (!is_no_texture_folder) { if (abName.EndsWith("_asset")) { string folder_name = abName.Substring(0, abName.Length - 6); string folder_path = "Assets/LuaFramework/AssetBundleRes/ui/" + folder_name + "/texture/"; path = folder_path + resName; if (File.Exists(path + ".png")) { return path + ".png"; } else if (File.Exists(path + ".jpg")) { return path + ".jpg"; } else { if (Directory.Exists(folder_path)) { DirectoryInfo direction = new DirectoryInfo(folder_path); FileInfo[] files = direction.GetFiles("*", SearchOption.AllDirectories); for (int i = 0; i < files.Length; i++) { // if (files[i].Name.StartsWith(resName)) if (files[i].Name == (resName+".png")) { path = files[i].FullName; return path; } } } } } else { string folder_path = "Assets/LuaFramework/AssetBundleRes/ui/" + abName + "/prefab/"; path = folder_path + resName + ".prefab"; if (File.Exists(path)) return path; } } return ""; } } [Serializable] public class FilePathRule { public string Type; public string Key; public List Paths; } [Serializable] public class FilePathRuleInfo { public List Rules; } #endif