| | |
| | | using UnityEngine.Video; |
| | | using Spine.Unity; |
| | | using UnityEngine.UI; |
| | | using Cysharp.Threading.Tasks; |
| | | using System.Threading; |
| | | using ProjSG.Resource; |
| | | |
| | | |
| | | |
| | |
| | | #endif |
| | | |
| | | //needExt 是否需要函数内部添加后缀 |
| | | [System.Obsolete("US2: Use LoadAssetAsync<T>(directory, name, needExt) returning UniTask<T> instead.")] |
| | | public T LoadAsset<T>(string directory, string name, bool needExt = true) where T : UnityEngine.Object |
| | | { |
| | | directory = directory.Replace("\\", "/"); |
| | | name = name.Replace("\\", "/"); |
| | | T asset = null; |
| | | // 特殊处理 因为有一层图集的关系 directory要传入的应该是atlas的名字 |
| | | if (typeof(T) == typeof(Sprite)) |
| | | { |
| | |
| | | } |
| | | else |
| | | { |
| | | if (!needExt) |
| | | { |
| | | //外部用到的自己加后缀,内部统一去除后缀名 |
| | | name = name.Substring(0, name.LastIndexOf(".")); |
| | | } |
| | | //TODO: 临时特殊处理打包后的路径读取 |
| | | if (directory == "UI" || directory == "UIComp" || directory.StartsWith("Sprite") |
| | | || directory == "Battle/Prefabs" || directory == "Materials") |
| | | { |
| | | directory = "UI/" + directory; |
| | | } |
| | | else if (name == "Hero_001") |
| | | { |
| | | directory = "UI/Hero/SpineRes"; |
| | | } |
| | | |
| | | else if (directory.Contains("Texture")) |
| | | { |
| | | directory = "maps/" + name; |
| | | } |
| | | else if (directory.Contains("Shader")) |
| | | { |
| | | directory = "graphic/shader"; |
| | | } |
| | | |
| | | |
| | | var assetInfo = new AssetInfo(directory.ToLower(), name.ToLower()); |
| | | asset = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo, typeof(T)) as T; |
| | | // US1: Route through YooAssetService sync wrapper (transitional) |
| | | #pragma warning disable CS0612, CS0618 |
| | | asset = YooAssetService.Instance.LoadAssetSync<T>(path); |
| | | #pragma warning restore CS0612, CS0618 |
| | | } |
| | | |
| | | if (asset == null) |
| | |
| | | return asset; |
| | | } |
| | | |
| | | [System.Obsolete("US2: Use LoadConfigAsync returning UniTask<string[]> instead.")] |
| | | public string[] LoadConfig(string name) |
| | | { |
| | | string path = string.Empty; |
| | |
| | | { |
| | | if (!AssetSource.isUseAssetBundle) |
| | | { |
| | | #pragma warning disable CS0618 // Obsolete — legacy sync fallback |
| | | SpriteAtlas atlas = LoadAsset<SpriteAtlas>("Sprite", atlasName.Replace("Sprite/", "")); |
| | | #pragma warning restore CS0618 |
| | | if (null == atlas) |
| | | { |
| | | return null; |
| | |
| | | } |
| | | |
| | | //needExt 是否需要函数内部添加后缀 |
| | | [System.Obsolete("US2: Use LoadAssetAsync<T>(directory, name, needExt) returning UniTask<T> instead.")] |
| | | public void LoadAssetAsync<T>(string directory, string name, Action<bool, UnityEngine.Object> callBack, bool needExt = true) where T : UnityEngine.Object |
| | | { |
| | | directory = directory.Replace("\\", "/"); |
| | |
| | | |
| | | private void LoadSpriteAsync<T>(string atlasName, string spriteName, Action<bool, UnityEngine.Object> callBack) where T : UnityEngine.Object |
| | | { |
| | | #if !UNITY_EDITOR |
| | | LoadAssetAsync<SpriteAtlas>(atlasName, spriteName, (isLoaded, atlas) => { |
| | | if (isLoaded) |
| | | if (!AssetSource.isUseAssetBundle) |
| | | { |
| | | // Editor 模式下可直接加载 sprite |
| | | LoadAssetAsyncInternal<T>(atlasName, spriteName, callBack); |
| | | } |
| | | else |
| | | { |
| | | // AB 模式下直接加载单独的 Sprite 文件(YooAsset 自动处理 SpriteAtlas 依赖) |
| | | LoadAssetAsyncInternal<Sprite>(atlasName, spriteName, (isLoaded, sprite) => |
| | | { |
| | | SpriteAtlas _atlas = atlas as SpriteAtlas; |
| | | callBack?.Invoke(isLoaded, _atlas.GetSprite(spriteName)); |
| | | } |
| | | else |
| | | { |
| | | callBack?.Invoke(false, null); |
| | | } |
| | | }); |
| | | #else |
| | | // 编辑器下可以直接加载没啥问题 |
| | | LoadAssetAsyncInternal<T>(atlasName, spriteName, callBack); |
| | | #endif |
| | | callBack?.Invoke(isLoaded, sprite); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | private void LoadAssetAsyncInternal<T>(string directory, string name, Action<bool, UnityEngine.Object> callBack, bool needExt = true) where T : UnityEngine.Object |
| | |
| | | } |
| | | else |
| | | { |
| | | var assetInfo = new AssetInfo(directory.ToLower(), name.ToLower()); |
| | | AssetBundleUtility.Instance.Co_LoadAsset(assetInfo, callBack); |
| | | // US1: Route through YooAssetService async |
| | | CoLoadViaYooAsset<T>(path, callBack).Forget(); |
| | | } |
| | | } |
| | | |
| | | public void UnloadAsset(string assetBundleName, string assetName) |
| | | private async UniTaskVoid CoLoadViaYooAsset<T>(string path, Action<bool, UnityEngine.Object> callBack, CancellationToken ct = default) where T : UnityEngine.Object |
| | | { |
| | | if (!AssetSource.isUseAssetBundle) |
| | | return; |
| | | |
| | | AssetBundleUtility.Instance.UnloadAsset(assetBundleName, assetName); |
| | | try |
| | | { |
| | | var asset = await YooAssetService.Instance.LoadAssetAsync<T>(path, ct: ct); |
| | | callBack?.Invoke(asset != null, asset); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Debug.LogError($"[ResManager] Async load via YooAsset failed: {ex.Message}"); |
| | | callBack?.Invoke(false, null); |
| | | } |
| | | } |
| | | |
| | | [System.Obsolete("US1: Use YooAssetService.ReleaseHandle or UnloadUnusedAssetsAsync instead.")] |
| | | public void UnloadAsset(string assetBundleName, string assetName) |
| | | { |
| | | // US1: AssetBundleUtility unload no longer effective since assets loaded via YooAsset. |
| | | // Proper unload handled via YooAssetService handle-based release. |
| | | } |
| | | |
| | | [System.Obsolete("US1: Use YooAssetService.UnloadUnusedAssetsAsync instead.")] |
| | | public void UnloadAssetBundle(string assetBundleName, bool unloadAllLoadedObjects, bool includeDependenice) |
| | | { |
| | | if (!AssetSource.isUseAssetBundle) |
| | | return; |
| | | AssetBundleUtility.Instance.UnloadAssetBundle(assetBundleName, unloadAllLoadedObjects, includeDependenice); |
| | | // US1: AssetBundleUtility unload no longer effective since assets loaded via YooAsset. |
| | | } |
| | | |
| | | public string GetAssetFilePath(string _assetKey) |
| | |
| | | return path; |
| | | } |
| | | |
| | | // ==================================================================== |
| | | // US1: New UniTask-based async variants |
| | | // ==================================================================== |
| | | |
| | | /// <summary> |
| | | /// 异步加载资源(UniTask 版本,US1 新增)。 |
| | | /// </summary> |
| | | public async UniTask<T> LoadAssetAsync<T>(string directory, string name, bool needExt = true, CancellationToken ct = default) where T : UnityEngine.Object |
| | | { |
| | | directory = directory.Replace("\\", "/"); |
| | | name = name.Replace("\\", "/"); |
| | | |
| | | if (typeof(T) == typeof(Sprite)) |
| | | { |
| | | return await LoadSpriteAsyncUniTask(directory, name, ct) as T; |
| | | } |
| | | |
| | | if (typeof(T) == typeof(SkeletonDataAsset)) |
| | | { |
| | | if (name.Contains("/")) |
| | | { |
| | | directory += name.Substring(0, name.LastIndexOf("/")); |
| | | name = name.Substring(name.LastIndexOf("/") + 1); |
| | | } |
| | | } |
| | | |
| | | var path = ($"Assets/ResourcesOut/{directory}/{name}" + (needExt ? GetExtension(typeof(T)) : "")) |
| | | .Replace("//", "/").Trim().Replace("\\", "/"); |
| | | |
| | | if (!AssetSource.isUseAssetBundle) |
| | | { |
| | | #if UNITY_EDITOR |
| | | return UnityEditor.AssetDatabase.LoadAssetAtPath<T>(path); |
| | | #else |
| | | return null; |
| | | #endif |
| | | } |
| | | |
| | | return await YooAssetService.Instance.LoadAssetAsync<T>(path, ct: ct); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// US4: 异步加载资源并走缓存层(缓存命中直接返回,未命中则加载并缓存)。 |
| | | /// </summary> |
| | | public async UniTask<T> LoadAssetCachedAsync<T>(string directory, string name, bool needExt = true, CancellationToken ct = default) where T : UnityEngine.Object |
| | | { |
| | | directory = directory.Replace("\\", "/"); |
| | | name = name.Replace("\\", "/"); |
| | | |
| | | var path = ($"Assets/ResourcesOut/{directory}/{name}" + (needExt ? GetExtension(typeof(T)) : "")) |
| | | .Replace("//", "/").Trim().Replace("\\", "/"); |
| | | |
| | | if (!AssetSource.isUseAssetBundle) |
| | | { |
| | | #if UNITY_EDITOR |
| | | return UnityEditor.AssetDatabase.LoadAssetAtPath<T>(path); |
| | | #else |
| | | return null; |
| | | #endif |
| | | } |
| | | |
| | | return await ResourceCacheManager.Instance.GetOrLoadAsync<T>(path); |
| | | } |
| | | |
| | | private async UniTask<Sprite> LoadSpriteAsyncUniTask(string atlasName, string spriteName, CancellationToken ct = default) |
| | | { |
| | | if (!AssetSource.isUseAssetBundle) |
| | | { |
| | | var atlas = await LoadAssetAsync<SpriteAtlas>("Sprite", atlasName.Replace("Sprite/", ""), ct: ct); |
| | | return atlas?.GetSprite(spriteName); |
| | | } |
| | | else |
| | | { |
| | | var path = $"Assets/ResourcesOut/{atlasName}/{spriteName}.png" |
| | | .Replace("//", "/").Trim().Replace("\\", "/"); |
| | | return await YooAssetService.Instance.LoadAssetAsync<Sprite>(path, ct: ct); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 异步加载配置文件(UniTask 版本)。 |
| | | /// WebGL 平台使用 YooAsset RawFile 异步加载,其他平台使用线程池。 |
| | | /// </summary> |
| | | public async UniTask<string[]> LoadConfigAsync(string name, CancellationToken ct = default) |
| | | { |
| | | #if UNITY_WEBGL && !UNITY_EDITOR |
| | | // WebGL 不支持多线程和 File.ReadAllLines,使用 YooAsset RawFile |
| | | try |
| | | { |
| | | var text = await ProjSG.Resource.YooAssetService.Instance.LoadRawFileTextAsync($"config/{name}", ct); |
| | | if (!string.IsNullOrEmpty(text)) |
| | | { |
| | | return text.Split(new[] { "\r\n", "\n" }, System.StringSplitOptions.None); |
| | | } |
| | | } |
| | | catch (System.Exception ex) |
| | | { |
| | | UnityEngine.Debug.LogError($"[ResManager] LoadConfigAsync WebGL fallback failed for '{name}': {ex.Message}"); |
| | | } |
| | | return System.Array.Empty<string>(); |
| | | #else |
| | | #pragma warning disable CS0618 // LoadConfig is obsolete — used here as thread-pool fallback for non-WebGL |
| | | return await UniTask.RunOnThreadPool(() => LoadConfig(name)); |
| | | #pragma warning restore CS0618 |
| | | #endif |
| | | } |
| | | |
| | | } |