com.alicizax.unity.tuyoogam.../Runtime/ResourceManager/ResourceManager.cs

419 lines
17 KiB
C#
Raw Normal View History

2025-01-09 11:31:04 +08:00
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace YooAsset
{
internal class ResourceManager
{
2025-02-28 16:11:01 +08:00
internal readonly Dictionary<string, ProviderOperation> ProviderDic = new Dictionary<string, ProviderOperation>(5000);
internal readonly Dictionary<string, LoadBundleFileOperation> LoaderDic = new Dictionary<string, LoadBundleFileOperation>(5000);
internal readonly List<SceneHandle> SceneHandles = new List<SceneHandle>(100);
2025-01-09 11:31:04 +08:00
private long _sceneCreateIndex = 0;
private IBundleQuery _bundleQuery;
2025-04-01 21:12:28 +08:00
private int _bundleLoadingMaxConcurrency;
2025-01-09 11:31:04 +08:00
/// <summary>
/// 所属包裹
/// </summary>
public readonly string PackageName;
2025-02-28 16:11:01 +08:00
/// <summary>
/// 锁定加载操作
/// </summary>
public bool LockLoadOperation = false;
2025-04-01 21:12:28 +08:00
/// <summary>
/// 统计正在加载的Bundle文件数量
/// </summary>
public int BundleLoadingCounter = 0;
2025-01-09 11:31:04 +08:00
public ResourceManager(string packageName)
{
PackageName = packageName;
}
/// <summary>
/// 初始化
/// </summary>
2025-04-01 21:12:28 +08:00
public void Initialize(InitializeParameters parameters, IBundleQuery bundleServices)
2025-01-09 11:31:04 +08:00
{
2025-04-01 21:12:28 +08:00
_bundleLoadingMaxConcurrency = parameters.BundleLoadingMaxConcurrency;
2025-01-09 11:31:04 +08:00
_bundleQuery = bundleServices;
SceneManager.sceneUnloaded += OnSceneUnloaded;
}
/// <summary>
/// 销毁管理器
/// </summary>
public void Destroy()
{
SceneManager.sceneUnloaded -= OnSceneUnloaded;
}
/// <summary>
/// 尝试卸载指定资源的资源包(包括依赖资源)
/// </summary>
public void TryUnloadUnusedAsset(AssetInfo assetInfo)
{
if (assetInfo.IsInvalid)
{
YooLogger.Error($"Failed to unload asset ! {assetInfo.Error}");
return;
}
// 卸载主资源包加载器
string mainBundleName = _bundleQuery.GetMainBundleName(assetInfo);
var mainLoader = TryGetBundleFileLoader(mainBundleName);
if (mainLoader != null)
{
mainLoader.TryDestroyProviders();
if (mainLoader.CanDestroyLoader())
{
string bundleName = mainLoader.LoadBundleInfo.Bundle.BundleName;
mainLoader.DestroyLoader();
2025-02-28 16:11:01 +08:00
LoaderDic.Remove(bundleName);
2025-01-09 11:31:04 +08:00
}
}
// 卸载依赖资源包加载器
string[] dependBundleNames = _bundleQuery.GetDependBundleNames(assetInfo);
foreach (var dependBundleName in dependBundleNames)
{
var dependLoader = TryGetBundleFileLoader(dependBundleName);
if (dependLoader != null)
{
if (dependLoader.CanDestroyLoader())
{
string bundleName = dependLoader.LoadBundleInfo.Bundle.BundleName;
dependLoader.DestroyLoader();
2025-02-28 16:11:01 +08:00
LoaderDic.Remove(bundleName);
2025-01-09 11:31:04 +08:00
}
}
}
}
/// <summary>
/// 加载场景对象
/// 注意:返回的场景句柄是唯一的,每个场景句柄对应自己的场景提供者对象。
/// 注意:业务逻辑层应该避免同时加载一个子场景。
/// </summary>
public SceneHandle LoadSceneAsync(AssetInfo assetInfo, LoadSceneParameters loadSceneParams, bool suspendLoad, uint priority)
{
2025-02-28 16:11:01 +08:00
if (LockLoadOperation)
{
string error = $"The load operation locked !";
YooLogger.Error(error);
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(error);
return completedProvider.CreateHandle<SceneHandle>();
}
2025-01-09 11:31:04 +08:00
if (assetInfo.IsInvalid)
{
YooLogger.Error($"Failed to load scene ! {assetInfo.Error}");
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(assetInfo.Error);
return completedProvider.CreateHandle<SceneHandle>();
}
// 注意同一个场景的ProviderGUID每次加载都会变化
string providerGUID = $"{assetInfo.GUID}-{++_sceneCreateIndex}";
ProviderOperation provider;
{
provider = new SceneProvider(this, providerGUID, assetInfo, loadSceneParams, suspendLoad);
2025-04-01 21:12:28 +08:00
provider.InitProviderDebugInfo();
2025-02-28 16:11:01 +08:00
ProviderDic.Add(providerGUID, provider);
2025-01-09 11:31:04 +08:00
OperationSystem.StartOperation(PackageName, provider);
}
provider.Priority = priority;
var handle = provider.CreateHandle<SceneHandle>();
handle.PackageName = PackageName;
2025-02-28 16:11:01 +08:00
SceneHandles.Add(handle);
2025-01-09 11:31:04 +08:00
return handle;
}
/// <summary>
/// 加载资源对象
/// </summary>
public AssetHandle LoadAssetAsync(AssetInfo assetInfo, uint priority)
{
2025-02-28 16:11:01 +08:00
if (LockLoadOperation)
{
string error = $"The load operation locked !";
YooLogger.Error(error);
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(error);
return completedProvider.CreateHandle<AssetHandle>();
}
2025-01-09 11:31:04 +08:00
if (assetInfo.IsInvalid)
{
YooLogger.Error($"Failed to load asset ! {assetInfo.Error}");
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(assetInfo.Error);
return completedProvider.CreateHandle<AssetHandle>();
}
string providerGUID = nameof(LoadAssetAsync) + assetInfo.GUID;
ProviderOperation provider = TryGetAssetProvider(providerGUID);
if (provider == null)
{
provider = new AssetProvider(this, providerGUID, assetInfo);
2025-04-01 21:12:28 +08:00
provider.InitProviderDebugInfo();
2025-02-28 16:11:01 +08:00
ProviderDic.Add(providerGUID, provider);
2025-01-09 11:31:04 +08:00
OperationSystem.StartOperation(PackageName, provider);
}
provider.Priority = priority;
return provider.CreateHandle<AssetHandle>();
}
/// <summary>
/// 加载子资源对象
/// </summary>
public SubAssetsHandle LoadSubAssetsAsync(AssetInfo assetInfo, uint priority)
{
2025-02-28 16:11:01 +08:00
if (LockLoadOperation)
{
string error = $"The load operation locked !";
YooLogger.Error(error);
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(error);
return completedProvider.CreateHandle<SubAssetsHandle>();
}
2025-01-09 11:31:04 +08:00
if (assetInfo.IsInvalid)
{
YooLogger.Error($"Failed to load sub assets ! {assetInfo.Error}");
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(assetInfo.Error);
return completedProvider.CreateHandle<SubAssetsHandle>();
}
string providerGUID = nameof(LoadSubAssetsAsync) + assetInfo.GUID;
ProviderOperation provider = TryGetAssetProvider(providerGUID);
if (provider == null)
{
provider = new SubAssetsProvider(this, providerGUID, assetInfo);
2025-04-01 21:12:28 +08:00
provider.InitProviderDebugInfo();
2025-02-28 16:11:01 +08:00
ProviderDic.Add(providerGUID, provider);
2025-01-09 11:31:04 +08:00
OperationSystem.StartOperation(PackageName, provider);
}
provider.Priority = priority;
return provider.CreateHandle<SubAssetsHandle>();
}
/// <summary>
/// 加载所有资源对象
/// </summary>
public AllAssetsHandle LoadAllAssetsAsync(AssetInfo assetInfo, uint priority)
{
2025-02-28 16:11:01 +08:00
if (LockLoadOperation)
{
string error = $"The load operation locked !";
YooLogger.Error(error);
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(error);
return completedProvider.CreateHandle<AllAssetsHandle>();
}
2025-01-09 11:31:04 +08:00
if (assetInfo.IsInvalid)
{
YooLogger.Error($"Failed to load all assets ! {assetInfo.Error}");
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(assetInfo.Error);
return completedProvider.CreateHandle<AllAssetsHandle>();
}
string providerGUID = nameof(LoadAllAssetsAsync) + assetInfo.GUID;
ProviderOperation provider = TryGetAssetProvider(providerGUID);
if (provider == null)
{
provider = new AllAssetsProvider(this, providerGUID, assetInfo);
2025-04-01 21:12:28 +08:00
provider.InitProviderDebugInfo();
2025-02-28 16:11:01 +08:00
ProviderDic.Add(providerGUID, provider);
2025-01-09 11:31:04 +08:00
OperationSystem.StartOperation(PackageName, provider);
}
provider.Priority = priority;
return provider.CreateHandle<AllAssetsHandle>();
}
/// <summary>
/// 加载原生文件
/// </summary>
public RawFileHandle LoadRawFileAsync(AssetInfo assetInfo, uint priority)
{
2025-02-28 16:11:01 +08:00
if (LockLoadOperation)
{
string error = $"The load operation locked !";
YooLogger.Error(error);
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(error);
return completedProvider.CreateHandle<RawFileHandle>();
}
2025-01-09 11:31:04 +08:00
if (assetInfo.IsInvalid)
{
YooLogger.Error($"Failed to load raw file ! {assetInfo.Error}");
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(assetInfo.Error);
return completedProvider.CreateHandle<RawFileHandle>();
}
string providerGUID = nameof(LoadRawFileAsync) + assetInfo.GUID;
ProviderOperation provider = TryGetAssetProvider(providerGUID);
if (provider == null)
{
provider = new RawFileProvider(this, providerGUID, assetInfo);
2025-04-01 21:12:28 +08:00
provider.InitProviderDebugInfo();
2025-02-28 16:11:01 +08:00
ProviderDic.Add(providerGUID, provider);
2025-01-09 11:31:04 +08:00
OperationSystem.StartOperation(PackageName, provider);
}
provider.Priority = priority;
return provider.CreateHandle<RawFileHandle>();
}
internal LoadBundleFileOperation CreateMainBundleFileLoader(AssetInfo assetInfo)
{
BundleInfo bundleInfo = _bundleQuery.GetMainBundleInfo(assetInfo);
return CreateBundleFileLoaderInternal(bundleInfo);
}
internal List<LoadBundleFileOperation> CreateDependBundleFileLoaders(AssetInfo assetInfo)
{
BundleInfo[] bundleInfos = _bundleQuery.GetDependBundleInfos(assetInfo);
List<LoadBundleFileOperation> result = new List<LoadBundleFileOperation>(bundleInfos.Length);
foreach (var bundleInfo in bundleInfos)
{
var bundleLoader = CreateBundleFileLoaderInternal(bundleInfo);
result.Add(bundleLoader);
}
return result;
}
internal void RemoveBundleProviders(List<ProviderOperation> removeList)
{
foreach (var provider in removeList)
{
2025-02-28 16:11:01 +08:00
ProviderDic.Remove(provider.ProviderGUID);
2025-01-09 11:31:04 +08:00
}
}
2025-02-28 16:11:01 +08:00
internal bool CheckBundleDestroyed(int bundleID)
{
string bundleName = _bundleQuery.GetMainBundleName(bundleID);
var bundleFileLoader = TryGetBundleFileLoader(bundleName);
if (bundleFileLoader == null)
return true;
return bundleFileLoader.IsDestroyed;
}
2025-01-09 11:31:04 +08:00
internal bool HasAnyLoader()
{
2025-02-28 16:11:01 +08:00
return LoaderDic.Count > 0;
2025-01-09 11:31:04 +08:00
}
2025-04-01 21:12:28 +08:00
internal bool BundleLoadingIsBusy()
{
return BundleLoadingCounter >= _bundleLoadingMaxConcurrency;
}
2025-01-09 11:31:04 +08:00
private LoadBundleFileOperation CreateBundleFileLoaderInternal(BundleInfo bundleInfo)
{
// 如果加载器已经存在
string bundleName = bundleInfo.Bundle.BundleName;
LoadBundleFileOperation loaderOperation = TryGetBundleFileLoader(bundleName);
if (loaderOperation != null)
return loaderOperation;
// 新增下载需求
loaderOperation = new LoadBundleFileOperation(this, bundleInfo);
2025-02-28 16:11:01 +08:00
LoaderDic.Add(bundleName, loaderOperation);
2025-01-09 11:31:04 +08:00
return loaderOperation;
}
private LoadBundleFileOperation TryGetBundleFileLoader(string bundleName)
{
2025-02-28 16:11:01 +08:00
if (LoaderDic.TryGetValue(bundleName, out LoadBundleFileOperation value))
2025-01-09 11:31:04 +08:00
return value;
else
return null;
}
private ProviderOperation TryGetAssetProvider(string providerGUID)
{
2025-02-28 16:11:01 +08:00
if (ProviderDic.TryGetValue(providerGUID, out ProviderOperation value))
2025-01-09 11:31:04 +08:00
return value;
else
return null;
}
private void OnSceneUnloaded(Scene scene)
{
List<SceneHandle> removeList = new List<SceneHandle>();
2025-02-28 16:11:01 +08:00
foreach (var sceneHandle in SceneHandles)
2025-01-09 11:31:04 +08:00
{
if (sceneHandle.IsValid)
{
if (sceneHandle.SceneObject == scene)
{
sceneHandle.Release();
removeList.Add(sceneHandle);
}
}
}
foreach (var sceneHandle in removeList)
{
2025-02-28 16:11:01 +08:00
SceneHandles.Remove(sceneHandle);
2025-01-09 11:31:04 +08:00
}
}
#region
2025-02-28 16:11:01 +08:00
internal List<DebugProviderInfo> GetDebugProviderInfos()
2025-01-09 11:31:04 +08:00
{
2025-02-28 16:11:01 +08:00
List<DebugProviderInfo> result = new List<DebugProviderInfo>(ProviderDic.Count);
foreach (var provider in ProviderDic.Values)
2025-01-09 11:31:04 +08:00
{
DebugProviderInfo providerInfo = new DebugProviderInfo();
providerInfo.AssetPath = provider.MainAssetInfo.AssetPath;
providerInfo.SpawnScene = provider.SpawnScene;
2025-04-01 21:12:28 +08:00
providerInfo.BeginTime = provider.BeginTime;
providerInfo.LoadingTime = provider.ProcessTime;
2025-01-09 11:31:04 +08:00
providerInfo.RefCount = provider.RefCount;
providerInfo.Status = provider.Status.ToString();
2025-02-28 16:11:01 +08:00
providerInfo.DependBundles = provider.GetDebugDependBundles();
2025-01-09 11:31:04 +08:00
result.Add(providerInfo);
}
return result;
}
2025-02-28 16:11:01 +08:00
internal List<DebugBundleInfo> GetDebugBundleInfos()
{
List<DebugBundleInfo> result = new List<DebugBundleInfo>(LoaderDic.Values.Count);
foreach (var bundleLoader in LoaderDic.Values)
{
var packageBundle = bundleLoader.LoadBundleInfo.Bundle;
var bundleInfo = new DebugBundleInfo();
bundleInfo.BundleName = packageBundle.BundleName;
bundleInfo.RefCount = bundleLoader.RefCount;
2025-04-01 21:12:28 +08:00
bundleInfo.Status = bundleLoader.Status.ToString();
2025-02-28 16:11:01 +08:00
bundleInfo.ReferenceBundles = FilterReferenceBundles(packageBundle);
result.Add(bundleInfo);
}
return result;
}
internal List<string> FilterReferenceBundles(PackageBundle packageBundle)
{
// 注意:引用的资源包不一定在内存中,所以需要过滤
var referenceBundles = packageBundle.GetDebugReferenceBundles();
List<string> result = new List<string>(referenceBundles.Count);
foreach (var bundleName in referenceBundles)
{
if (LoaderDic.ContainsKey(bundleName))
result.Add(bundleName);
}
return result;
}
2025-01-09 11:31:04 +08:00
#endregion
}
}