using System; using System.Collections.Generic; using System.Text; using UnityEngine; namespace TinaX { public static class XConfig { public static string ConfigResourcesPath { get;} = $"Assets/Resources/{ConfigRootFolderInResource}"; public const string ConfigRootFolderInResource = "XConfig"; //以Resources.Load视角下的ResourcesPath; //private static List<> private const string mPathHeadText_LoadByResources = "ures:"; private const string mPathHeadText_LoadByVFS = "xvfs:"; /// /// key: path(附带头), value: 缓存对象 /// private static Dictionary mDict_ConfigCache = new Dictionary(); private static Dictionary mDict_JsonCache = new Dictionary(); public static void RefreshConfigs() { } /// /// Get Unity Config /// /// /// /// 优先从缓存中读取 /// public static T GetConfig(string configPath , AssetLoadType loadType = AssetLoadType.Resources, bool cachePrior = true) where T : UnityEngine.ScriptableObject { bool cache_flag = false; string cache_key = ((loadType == AssetLoadType.Resources) ? mPathHeadText_LoadByResources : mPathHeadText_LoadByVFS) + configPath; if (cachePrior && UnityEngine.Application.isPlaying) { //检查缓存 if (mDict_ConfigCache.TryGetValue(cache_key, out object conf)) return conf as T; else cache_flag = true; //加载之后要加入缓存字典 } T final_asset; //load asset if(loadType == AssetLoadType.Resources) { #if UNITY_EDITOR if (Application.isPlaying) { string _final_path = (configPath.StartsWith("/") ? ConfigRootFolderInResource + configPath : ConfigRootFolderInResource + "/" + configPath); _final_path = RemoveExtNameIfExists(_final_path); final_asset = Resources.Load(_final_path); } else { //在编辑器下应该使用AssetDatabase加载 if (configPath.IndexOf("Resources") != -1 && configPath.StartsWith("Assets/")) { //本来给定的就是unity asset path, 直接加载 final_asset = UnityEditor.AssetDatabase.LoadAssetAtPath(configPath); } else { //本来的路径是Resources的路径,要还原成Unity的路径 string uPath = ConfigResourcesPath + "/" + configPath; if (!uPath.EndsWith(".asset")) uPath = uPath + ".asset"; final_asset = UnityEditor.AssetDatabase.LoadAssetAtPath(uPath); } } #else string _final_path = (configPath.StartsWith("/") ? ConfigRootFolderInResource + configPath : ConfigRootFolderInResource + "/" + configPath); _final_path = RemoveExtNameIfExists(_final_path); final_asset = Resources.Load(_final_path); #endif } else if(loadType == AssetLoadType.VFS) { #if UNITY_EDITOR if(Application.isPlaying && XCore.MainInstance != null && XCore.GetMainInstance().IsRunning) { final_asset = XCore.GetMainInstance().GetService().Load(configPath); } else { //editor only : load asset by assetdatabase. final_asset = UnityEditor.AssetDatabase.LoadAssetAtPath(configPath); } #else final_asset = XCore.GetMainInstance()?.GetService()?.Load(configPath); #endif } else { throw new Exception($"[TinaX] XConfig System can't load asset by \"{loadType.ToString()}\"loadtype."); } if (cache_flag) { if (mDict_ConfigCache.ContainsKey(cache_key)) mDict_ConfigCache[cache_key] = final_asset; else mDict_ConfigCache.Add(cache_key, final_asset); } return final_asset; } public static object GetConfig(string configPath, Type type, AssetLoadType loadType = AssetLoadType.Resources, bool cachePrior = true) { if (!type.IsSubclassOf(typeof(UnityEngine.ScriptableObject))) { Debug.LogError("[TinaX] XConfig : the config you want get is not valid \"ScriptableObject\"Type. type: " + type.FullName + " path:" + configPath); return null; } bool cache_flag = false; string cache_key = ((loadType == AssetLoadType.Resources) ? mPathHeadText_LoadByResources : mPathHeadText_LoadByVFS) + configPath; if (cachePrior && UnityEngine.Application.isPlaying) { //检查缓存 if (mDict_ConfigCache.TryGetValue(cache_key, out object conf)) return conf; else cache_flag = true; //加载之后要加入缓存字典 } object final_asset; //load asset if (loadType == AssetLoadType.Resources) { #if UNITY_EDITOR if (Application.isPlaying) { string _final_path = (configPath.StartsWith("/") ? ConfigRootFolderInResource + configPath : ConfigRootFolderInResource + "/" + configPath); _final_path = RemoveExtNameIfExists(_final_path); final_asset = Resources.Load(_final_path, type); } else { //在编辑器下应该使用AssetDatabase加载 if (configPath.IndexOf("Resources") != -1 && configPath.StartsWith("Assets/")) { //本来给定的就是unity asset path, 直接加载 final_asset = UnityEditor.AssetDatabase.LoadAssetAtPath(configPath, type); } else { //本来的路径是Resources的路径,要还原成Unity的路径 string uPath = ConfigResourcesPath + "/" + configPath; if (!uPath.EndsWith(".asset")) uPath += ".asset"; final_asset = UnityEditor.AssetDatabase.LoadAssetAtPath(uPath, type); } } #else string _final_path = (configPath.StartsWith("/") ? ConfigRootFolderInResource + configPath : ConfigRootFolderInResource + "/" + configPath); _final_path = RemoveExtNameIfExists(_final_path); final_asset = Resources.Load(_final_path, type); #endif } else if (loadType == AssetLoadType.VFS) { #if UNITY_EDITOR if (Application.isPlaying && XCore.MainInstance != null && XCore.GetMainInstance().IsRunning) { final_asset = XCore.GetMainInstance().GetService().Load(configPath,type); } else { //editor only : load asset by assetdatabase. final_asset = UnityEditor.AssetDatabase.LoadAssetAtPath(configPath,type); } #else final_asset = XCore.GetMainInstance()?.GetService()?.Load(configPath,type); #endif } else { throw new Exception($"[TinaX] XConfig System can't load asset by \"{loadType.ToString()}\"loadtype."); } if (cache_flag) { if (mDict_ConfigCache.ContainsKey(cache_key)) mDict_ConfigCache[cache_key] = final_asset; else mDict_ConfigCache.Add(cache_key, final_asset); } return final_asset; } public static T GetJson(string jsonPath, AssetLoadType loadType = AssetLoadType.SystemIO, bool cachePrior = false) { bool cache_flag = false; string cache_key = jsonPath.ToLower(); if (cachePrior && UnityEngine.Application.isPlaying) { //检查缓存 if (mDict_JsonCache.TryGetValue(cache_key, out object conf)) return (T)conf; else cache_flag = true; //加载之后要加入缓存字典 } T final_asset; //load asset if (loadType == AssetLoadType.Resources) { #if UNITY_EDITOR //在编辑器下应该使用AssetDatabase加载 if (jsonPath.IndexOf("Resources") != -1 && jsonPath.StartsWith("Assets/")) { //本来给定的就是unity asset path, 直接加载 var json_ta = UnityEditor.AssetDatabase.LoadAssetAtPath(jsonPath); final_asset = JsonUtility.FromJson(json_ta.text); } else { //本来的路径是Resources的路径,要还原成Unity的路径 string uPath = ConfigResourcesPath + "/" + jsonPath; if (!uPath.EndsWith(".asset")) uPath = uPath + ".asset"; var json_ta = UnityEditor.AssetDatabase.LoadAssetAtPath(uPath); final_asset = JsonUtility.FromJson(json_ta.text); } #else var json_ta = Resources.Load(RemoveExtNameIfExists(jsonPath)); final_asset = JsonUtility.FromJson(json_ta.text); #endif } else if (loadType == AssetLoadType.VFS) { #if UNITY_EDITOR if (Application.isPlaying && XCore.MainInstance != null && XCore.GetMainInstance().IsRunning) { var json_textAsset = XCore.GetMainInstance().GetService().Load(jsonPath); final_asset = JsonUtility.FromJson(json_textAsset.text); } else { //editor only : load asset by assetdatabase. var json_textAsset = UnityEditor.AssetDatabase.LoadAssetAtPath(jsonPath); final_asset = JsonUtility.FromJson(json_textAsset.text); } #else var json_textAsset = XCore.GetMainInstance()?.GetService()?.Load(jsonPath); final_asset = JsonUtility.FromJson(json_textAsset.text); #endif } else if(loadType == AssetLoadType.SystemIO) { var json_text = System.IO.File.ReadAllText(jsonPath, Encoding.UTF8); final_asset = JsonUtility.FromJson(json_text); } else { throw new Exception($"[TinaX] XConfig System can't load asset by \"{loadType.ToString()}\"loadtype."); } if (cache_flag) { if (mDict_ConfigCache.ContainsKey(cache_key)) mDict_ConfigCache[cache_key] = final_asset; else mDict_ConfigCache.Add(cache_key, final_asset); } return final_asset; } public static void SaveJson(object jsonContent,string json_path) { var json = JsonUtility.ToJson(jsonContent); TinaX.IO.XDirectory.CreateIfNotExists(System.IO.Path.GetDirectoryName(json_path)); TinaX.IO.XFile.DeleteIfExists(json_path); System.IO.File.WriteAllText(json_path, json, Encoding.UTF8); } #if UNITY_EDITOR public static T CreateConfigIfNotExists(string configPath, AssetLoadType pathType = AssetLoadType.Resources) where T: ScriptableObject { UnityEditor.AssetDatabase.ReleaseCachedFileHandles(); //检查路径 var final_path = (pathType == AssetLoadType.Resources) ? (ConfigResourcesPath + "/" + configPath + ".asset") : configPath; var asset = UnityEditor.AssetDatabase.LoadAssetAtPath(final_path); if(asset == null) { //create EnsureDirectory(final_path); var config = ScriptableObject.CreateInstance(); UnityEditor.AssetDatabase.CreateAsset(config, final_path); return config; } else { return asset; } } public static void SaveJson(object jsonContent, string jsonPath, AssetLoadType pathType) { //检查路径 var final_unity_path = (pathType == AssetLoadType.Resources) ? (ConfigResourcesPath + "/" + jsonPath + ".json") : jsonPath; var system_path = System.IO.Path.GetFullPath(final_unity_path); if (System.IO.File.Exists(system_path)) { System.IO.File.Delete(system_path) ; } var json_text = JsonUtility.ToJson(jsonContent); TinaX.IO.XDirectory.CreateIfNotExists(System.IO.Path.GetDirectoryName(system_path)); System.IO.File.WriteAllText(system_path, json_text, Encoding.UTF8); } private static void EnsureDirectory(string unityPath) { TinaX.IO.XDirectory.CreateIfNotExists( System.IO.Path.Combine( System.IO.Directory.GetCurrentDirectory(), System.IO.Path.GetDirectoryName(unityPath) ) ); } #endif /// /// 如果给定的路径有后缀名,则去掉后缀。 /// /// private static string RemoveExtNameIfExists(string source) { if (source.IsNullOrEmpty()) return source; int last_point = source.LastIndexOf('.'); int last_slash = source.LastIndexOf('/'); if (last_point > 0 && last_slash > 0 && last_slash > last_point) return source.Substring(0, last_point); else return source; } } }