using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using UnityEngine; using UnityEngine.SceneManagement; namespace YooAsset { internal class ResourceManager { // 全局场景句柄集合 private readonly static Dictionary _sceneHandles = new Dictionary(100); private static long _sceneCreateCount = 0; internal readonly Dictionary _providerDic = new Dictionary(5000); internal readonly Dictionary _loaderDic = new Dictionary(5000); private bool _simulationOnEditor; private IBundleQuery _bundleQuery; /// /// 所属包裹 /// public readonly string PackageName; public ResourceManager(string packageName) { PackageName = packageName; } /// /// 初始化 /// public void Initialize(InitializeParameters initializeParameters, IBundleQuery bundleServices) { _simulationOnEditor = initializeParameters is EditorSimulateModeParameters; _bundleQuery = bundleServices; } /// /// 尝试卸载指定资源的资源包(包括依赖资源) /// public void TryUnloadUnusedAsset(AssetInfo assetInfo) { if (assetInfo.IsInvalid) { YooLogger.Error($"Failed to unload asset ! {assetInfo.Error}"); return; } // 卸载主资源包加载器 string mainBundleName = _bundleQuery.GetMainBundleName(assetInfo); var mainLoader = TryGetFileLoader(mainBundleName); if (mainLoader != null) { mainLoader.TryDestroyProviders(); if (mainLoader.CanDestroyLoader()) { string bundleName = mainLoader.BundleFileInfo.Bundle.BundleName; mainLoader.DestroyLoader(); _loaderDic.Remove(bundleName); } } // 卸载依赖资源包加载器 string[] dependBundleNames = _bundleQuery.GetDependBundleNames(assetInfo); foreach (var dependBundleName in dependBundleNames) { var dependLoader = TryGetFileLoader(dependBundleName); if (dependLoader != null) { if (dependLoader.CanDestroyLoader()) { string bundleName = dependLoader.BundleFileInfo.Bundle.BundleName; dependLoader.DestroyLoader(); _loaderDic.Remove(bundleName); } } } } /// /// 加载场景对象 /// 注意:返回的场景句柄是唯一的,每个场景句柄对应自己的场景提供者对象。 /// 注意:业务逻辑层应该避免同时加载一个子场景。 /// public SceneHandle LoadSceneAsync(AssetInfo assetInfo, LoadSceneMode sceneMode, bool suspendLoad, uint priority, LocalPhysicsMode physicsMode = default) { if (assetInfo.IsInvalid) { YooLogger.Error($"Failed to load scene ! {assetInfo.Error}"); CompletedProvider completedProvider = new CompletedProvider(this, assetInfo); completedProvider.SetCompleted(assetInfo.Error); return completedProvider.CreateHandle(); } // 如果加载的是主场景,则卸载所有缓存的场景 if (sceneMode == LoadSceneMode.Single) { UnloadAllScene(); } // 注意:同一个场景的ProviderGUID每次加载都会变化 string providerGUID = $"{assetInfo.GUID}-{++_sceneCreateCount}"; ProviderOperation provider; { if (_simulationOnEditor) provider = new DatabaseSceneProvider(this, providerGUID, assetInfo, sceneMode, suspendLoad, physicsMode); else provider = new BundledSceneProvider(this, providerGUID, assetInfo, sceneMode, suspendLoad, physicsMode); provider.InitSpawnDebugInfo(); _providerDic.Add(providerGUID, provider); OperationSystem.StartOperation(PackageName, provider); } provider.Priority = priority; var handle = provider.CreateHandle(); handle.PackageName = PackageName; _sceneHandles.Add(providerGUID, handle); return handle; } /// /// 加载资源对象 /// public AssetHandle LoadAssetAsync(AssetInfo assetInfo, uint priority) { if (assetInfo.IsInvalid) { YooLogger.Error($"Failed to load asset ! {assetInfo.Error}"); CompletedProvider completedProvider = new CompletedProvider(this, assetInfo); completedProvider.SetCompleted(assetInfo.Error); return completedProvider.CreateHandle(); } string providerGUID = nameof(LoadAssetAsync) + assetInfo.GUID; ProviderOperation provider = TryGetProvider(providerGUID); if (provider == null) { if (_simulationOnEditor) provider = new DatabaseAssetProvider(this, providerGUID, assetInfo); else provider = new BundledAssetProvider(this, providerGUID, assetInfo); provider.InitSpawnDebugInfo(); _providerDic.Add(providerGUID, provider); OperationSystem.StartOperation(PackageName, provider); } provider.Priority = priority; return provider.CreateHandle(); } /// /// 加载子资源对象 /// public SubAssetsHandle LoadSubAssetsAsync(AssetInfo assetInfo, uint priority) { if (assetInfo.IsInvalid) { YooLogger.Error($"Failed to load sub assets ! {assetInfo.Error}"); CompletedProvider completedProvider = new CompletedProvider(this, assetInfo); completedProvider.SetCompleted(assetInfo.Error); return completedProvider.CreateHandle(); } string providerGUID = nameof(LoadSubAssetsAsync) + assetInfo.GUID; ProviderOperation provider = TryGetProvider(providerGUID); if (provider == null) { if (_simulationOnEditor) provider = new DatabaseSubAssetsProvider(this, providerGUID, assetInfo); else provider = new BundledSubAssetsProvider(this, providerGUID, assetInfo); provider.InitSpawnDebugInfo(); _providerDic.Add(providerGUID, provider); OperationSystem.StartOperation(PackageName, provider); } provider.Priority = priority; return provider.CreateHandle(); } /// /// 加载所有资源对象 /// public AllAssetsHandle LoadAllAssetsAsync(AssetInfo assetInfo, uint priority) { if (assetInfo.IsInvalid) { YooLogger.Error($"Failed to load all assets ! {assetInfo.Error}"); CompletedProvider completedProvider = new CompletedProvider(this, assetInfo); completedProvider.SetCompleted(assetInfo.Error); return completedProvider.CreateHandle(); } string providerGUID = nameof(LoadAllAssetsAsync) + assetInfo.GUID; ProviderOperation provider = TryGetProvider(providerGUID); if (provider == null) { if (_simulationOnEditor) provider = new DatabaseAllAssetsProvider(this, providerGUID, assetInfo); else provider = new BundledAllAssetsProvider(this, providerGUID, assetInfo); provider.InitSpawnDebugInfo(); _providerDic.Add(providerGUID, provider); OperationSystem.StartOperation(PackageName, provider); } provider.Priority = priority; return provider.CreateHandle(); } /// /// 加载原生文件 /// public RawFileHandle LoadRawFileAsync(AssetInfo assetInfo, uint priority) { if (assetInfo.IsInvalid) { YooLogger.Error($"Failed to load raw file ! {assetInfo.Error}"); CompletedProvider completedProvider = new CompletedProvider(this, assetInfo); completedProvider.SetCompleted(assetInfo.Error); return completedProvider.CreateHandle(); } string providerGUID = nameof(LoadRawFileAsync) + assetInfo.GUID; ProviderOperation provider = TryGetProvider(providerGUID); if (provider == null) { if (_simulationOnEditor) provider = new DatabaseRawFileProvider(this, providerGUID, assetInfo); else provider = new BundledRawFileProvider(this, providerGUID, assetInfo); provider.InitSpawnDebugInfo(); _providerDic.Add(providerGUID, provider); OperationSystem.StartOperation(PackageName, provider); } provider.Priority = priority; return provider.CreateHandle(); } internal void UnloadSubScene(string sceneName) { List removeKeys = new List(); foreach (var valuePair in _sceneHandles) { var sceneHandle = valuePair.Value; if (sceneHandle.SceneName == sceneName) { // 释放子场景句柄 sceneHandle.ReleaseInternal(); removeKeys.Add(valuePair.Key); } } foreach (string key in removeKeys) { _sceneHandles.Remove(key); } } internal void UnloadAllScene() { // 释放所有场景句柄 foreach (var valuePair in _sceneHandles) { valuePair.Value.ReleaseInternal(); } _sceneHandles.Clear(); } internal void ClearSceneHandle() { // 释放资源包下的所有场景 if (_bundleQuery.ManifestValid()) { string packageName = PackageName; List removeList = new List(); foreach (var valuePair in _sceneHandles) { if (valuePair.Value.PackageName == packageName) { removeList.Add(valuePair.Key); } } foreach (var key in removeList) { _sceneHandles.Remove(key); } } } internal LoadBundleFileOperation CreateMainBundleFileLoader(AssetInfo assetInfo) { BundleInfo bundleInfo = _bundleQuery.GetMainBundleInfo(assetInfo); return CreateFileLoaderInternal(bundleInfo); } internal LoadDependBundleFileOperation CreateDependFileLoaders(AssetInfo assetInfo) { BundleInfo[] bundleInfos = _bundleQuery.GetDependBundleInfos(assetInfo); List depends = new List(bundleInfos.Length); foreach (var bundleInfo in bundleInfos) { LoadBundleFileOperation dependLoader = CreateFileLoaderInternal(bundleInfo); depends.Add(dependLoader); } var operation = new LoadDependBundleFileOperation(depends); OperationSystem.StartOperation(PackageName, operation); return operation; } internal void RemoveBundleProviders(List removeList) { foreach (var provider in removeList) { _providerDic.Remove(provider.ProviderGUID); } } internal bool HasAnyLoader() { return _loaderDic.Count > 0; } private LoadBundleFileOperation CreateFileLoaderInternal(BundleInfo bundleInfo) { // 如果加载器已经存在 string bundleName = bundleInfo.Bundle.BundleName; LoadBundleFileOperation loaderOperation = TryGetFileLoader(bundleName); if (loaderOperation != null) return loaderOperation; // 新增下载需求 loaderOperation = new LoadBundleFileOperation(this, bundleInfo); OperationSystem.StartOperation(PackageName, loaderOperation); _loaderDic.Add(bundleName, loaderOperation); return loaderOperation; } private LoadBundleFileOperation TryGetFileLoader(string bundleName) { if (_loaderDic.TryGetValue(bundleName, out LoadBundleFileOperation value)) return value; else return null; } private ProviderOperation TryGetProvider(string providerGUID) { if (_providerDic.TryGetValue(providerGUID, out ProviderOperation value)) return value; else return null; } #region 调试信息 internal List GetDebugReportInfos() { List result = new List(_providerDic.Count); foreach (var provider in _providerDic.Values) { DebugProviderInfo providerInfo = new DebugProviderInfo(); providerInfo.AssetPath = provider.MainAssetInfo.AssetPath; providerInfo.SpawnScene = provider.SpawnScene; providerInfo.SpawnTime = provider.SpawnTime; providerInfo.LoadingTime = provider.LoadingTime; providerInfo.RefCount = provider.RefCount; providerInfo.Status = provider.Status.ToString(); providerInfo.DependBundleInfos = new List(); provider.GetBundleDebugInfos(providerInfo.DependBundleInfos); result.Add(providerInfo); } return result; } #endregion } }