TEngine 6

This commit is contained in:
Alex-Rachel
2025-03-07 23:09:46 +08:00
parent aad8ff3ee5
commit 551727687f
1988 changed files with 46223 additions and 94880 deletions

View File

@@ -9,16 +9,10 @@ namespace YooAsset
{
internal class ResourceManager
{
// 全局场景句柄集合
private readonly static Dictionary<string, SceneHandle> _sceneHandles = new Dictionary<string, SceneHandle>(100);
private static long _sceneCreateCount = 0;
private readonly Dictionary<string, ProviderBase> _providerDic = new Dictionary<string, ProviderBase>(5000);
private readonly Dictionary<string, BundleLoaderBase> _loaderDic = new Dictionary<string, BundleLoaderBase>(5000);
private readonly List<BundleLoaderBase> _loaderList = new List<BundleLoaderBase>(5000);
private bool _simulationOnEditor;
private bool _autoDestroyAssetProvider;
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);
private long _sceneCreateIndex = 0;
private IBundleQuery _bundleQuery;
/// <summary>
@@ -26,6 +20,11 @@ namespace YooAsset
/// </summary>
public readonly string PackageName;
/// <summary>
/// 锁定加载操作
/// </summary>
public bool LockLoadOperation = false;
public ResourceManager(string packageName)
{
@@ -35,49 +34,18 @@ namespace YooAsset
/// <summary>
/// 初始化
/// </summary>
public void Initialize(bool simulationOnEditor, bool autoDestroyAssetProvider, IBundleQuery bundleServices)
public void Initialize(IBundleQuery bundleServices)
{
_simulationOnEditor = simulationOnEditor;
_autoDestroyAssetProvider = autoDestroyAssetProvider;
_bundleQuery = bundleServices;
SceneManager.sceneUnloaded += OnSceneUnloaded;
}
/// <summary>
/// 更新
/// 销毁管理器
/// </summary>
public void Update()
public void Destroy()
{
foreach (var loader in _loaderList)
{
loader.Update();
if (_autoDestroyAssetProvider)
loader.TryDestroyProviders();
}
}
/// <summary>
/// 资源回收(卸载引用计数为零的资源)
/// </summary>
public void UnloadUnusedAssets()
{
for (int i = _loaderList.Count - 1; i >= 0; i--)
{
BundleLoaderBase loader = _loaderList[i];
loader.TryDestroyProviders();
}
for (int i = _loaderList.Count - 1; i >= 0; i--)
{
BundleLoaderBase loader = _loaderList[i];
if (loader.CanDestroy())
{
string bundleName = loader.MainBundleInfo.Bundle.BundleName;
loader.Destroy();
_loaderList.RemoveAt(i);
_loaderDic.Remove(bundleName);
}
}
SceneManager.sceneUnloaded -= OnSceneUnloaded;
}
/// <summary>
@@ -92,17 +60,16 @@ namespace YooAsset
}
// 卸载主资源包加载器
string manBundleName = _bundleQuery.GetMainBundleName(assetInfo);
var mainLoader = TryGetAssetBundleLoader(manBundleName);
string mainBundleName = _bundleQuery.GetMainBundleName(assetInfo);
var mainLoader = TryGetBundleFileLoader(mainBundleName);
if (mainLoader != null)
{
mainLoader.TryDestroyProviders();
if (mainLoader.CanDestroy())
if (mainLoader.CanDestroyLoader())
{
string bundleName = mainLoader.MainBundleInfo.Bundle.BundleName;
mainLoader.Destroy();
_loaderList.Remove(mainLoader);
_loaderDic.Remove(bundleName);
string bundleName = mainLoader.LoadBundleInfo.Bundle.BundleName;
mainLoader.DestroyLoader();
LoaderDic.Remove(bundleName);
}
}
@@ -110,109 +77,57 @@ namespace YooAsset
string[] dependBundleNames = _bundleQuery.GetDependBundleNames(assetInfo);
foreach (var dependBundleName in dependBundleNames)
{
var dependLoader = TryGetAssetBundleLoader(dependBundleName);
var dependLoader = TryGetBundleFileLoader(dependBundleName);
if (dependLoader != null)
{
if (dependLoader.CanDestroy())
if (dependLoader.CanDestroyLoader())
{
string bundleName = dependLoader.MainBundleInfo.Bundle.BundleName;
dependLoader.Destroy();
_loaderList.Remove(dependLoader);
_loaderDic.Remove(bundleName);
string bundleName = dependLoader.LoadBundleInfo.Bundle.BundleName;
dependLoader.DestroyLoader();
LoaderDic.Remove(bundleName);
}
}
}
}
/// <summary>
/// 强制回收所有资源
/// 注意:加载器在销毁后关联的下载器还会继续下载!
/// </summary>
public void ForceUnloadAllAssets()
{
#if UNITY_WEBGL
throw new Exception($"WebGL not support invoke {nameof(ForceUnloadAllAssets)}");
#else
// 注意:因为场景无法异步转同步,需要等待所有场景加载完毕!
foreach (var sceneHandlePair in _sceneHandles)
{
var sceneHandle = sceneHandlePair.Value;
if (sceneHandle.PackageName == PackageName)
{
if (sceneHandle.IsDone == false)
throw new Exception($"{nameof(ForceUnloadAllAssets)} cannot be called when loading the scene !");
}
}
// 释放所有资源句柄
foreach (var provider in _providerDic.Values)
{
provider.ReleaseAllHandles();
}
// 强制销毁资源提供者
foreach (var provider in _providerDic.Values)
{
provider.ForceDestroyComplete();
provider.Destroy();
}
// 强制销毁资源加载器
foreach (var loader in _loaderList)
{
loader.ForceDestroyComplete();
loader.Destroy();
}
// 清空数据
_providerDic.Clear();
_loaderList.Clear();
_loaderDic.Clear();
ClearSceneHandle();
// 注意:调用底层接口释放所有资源
Resources.UnloadUnusedAssets();
#endif
}
/// <summary>
/// 加载场景对象
/// 注意:返回的场景句柄是唯一的,每个场景句柄对应自己的场景提供者对象。
/// 注意:业务逻辑层应该避免同时加载一个子场景。
/// </summary>
public SceneHandle LoadSceneAsync(AssetInfo assetInfo, LoadSceneMode sceneMode, bool suspendLoad, uint priority)
public SceneHandle LoadSceneAsync(AssetInfo assetInfo, LoadSceneParameters loadSceneParams, bool suspendLoad, uint priority)
{
if (assetInfo.IsInvalid)
if (LockLoadOperation)
{
YooLogger.Error($"Failed to load scene ! {assetInfo.Error}");
CompletedProvider completedProvider = new CompletedProvider(assetInfo);
completedProvider.SetCompleted(assetInfo.Error);
string error = $"The load operation locked !";
YooLogger.Error(error);
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(error);
return completedProvider.CreateHandle<SceneHandle>();
}
// 如果加载的是主场景,则卸载所有缓存的场景
if (sceneMode == LoadSceneMode.Single)
if (assetInfo.IsInvalid)
{
UnloadAllScene();
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}-{++_sceneCreateCount}";
ProviderBase provider;
string providerGUID = $"{assetInfo.GUID}-{++_sceneCreateIndex}";
ProviderOperation provider;
{
if (_simulationOnEditor)
provider = new DatabaseSceneProvider(this, providerGUID, assetInfo, sceneMode, suspendLoad);
else
provider = new BundledSceneProvider(this, providerGUID, assetInfo, sceneMode, suspendLoad);
provider.InitSpawnDebugInfo();
_providerDic.Add(providerGUID, provider);
provider = new SceneProvider(this, providerGUID, assetInfo, loadSceneParams, suspendLoad);
provider.InitProviderDebugInfo();
ProviderDic.Add(providerGUID, provider);
OperationSystem.StartOperation(PackageName, provider);
}
provider.Priority = priority;
var handle = provider.CreateHandle<SceneHandle>();
handle.PackageName = PackageName;
_sceneHandles.Add(providerGUID, handle);
SceneHandles.Add(handle);
return handle;
}
@@ -221,24 +136,30 @@ namespace YooAsset
/// </summary>
public AssetHandle LoadAssetAsync(AssetInfo assetInfo, uint priority)
{
if (LockLoadOperation)
{
string error = $"The load operation locked !";
YooLogger.Error(error);
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(error);
return completedProvider.CreateHandle<AssetHandle>();
}
if (assetInfo.IsInvalid)
{
YooLogger.Error($"Failed to load asset ! {assetInfo.Error}");
CompletedProvider completedProvider = new CompletedProvider(assetInfo);
completedProvider.SetCompleted(assetInfo.Error);
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(assetInfo.Error);
return completedProvider.CreateHandle<AssetHandle>();
}
string providerGUID = nameof(LoadAssetAsync) + assetInfo.GUID;
ProviderBase provider = TryGetProvider(providerGUID);
ProviderOperation provider = TryGetAssetProvider(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);
provider = new AssetProvider(this, providerGUID, assetInfo);
provider.InitProviderDebugInfo();
ProviderDic.Add(providerGUID, provider);
OperationSystem.StartOperation(PackageName, provider);
}
@@ -251,24 +172,30 @@ namespace YooAsset
/// </summary>
public SubAssetsHandle LoadSubAssetsAsync(AssetInfo assetInfo, uint priority)
{
if (LockLoadOperation)
{
string error = $"The load operation locked !";
YooLogger.Error(error);
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(error);
return completedProvider.CreateHandle<SubAssetsHandle>();
}
if (assetInfo.IsInvalid)
{
YooLogger.Error($"Failed to load sub assets ! {assetInfo.Error}");
CompletedProvider completedProvider = new CompletedProvider(assetInfo);
completedProvider.SetCompleted(assetInfo.Error);
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(assetInfo.Error);
return completedProvider.CreateHandle<SubAssetsHandle>();
}
string providerGUID = nameof(LoadSubAssetsAsync) + assetInfo.GUID;
ProviderBase provider = TryGetProvider(providerGUID);
ProviderOperation provider = TryGetAssetProvider(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);
provider = new SubAssetsProvider(this, providerGUID, assetInfo);
provider.InitProviderDebugInfo();
ProviderDic.Add(providerGUID, provider);
OperationSystem.StartOperation(PackageName, provider);
}
@@ -281,24 +208,30 @@ namespace YooAsset
/// </summary>
public AllAssetsHandle LoadAllAssetsAsync(AssetInfo assetInfo, uint priority)
{
if (LockLoadOperation)
{
string error = $"The load operation locked !";
YooLogger.Error(error);
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(error);
return completedProvider.CreateHandle<AllAssetsHandle>();
}
if (assetInfo.IsInvalid)
{
YooLogger.Error($"Failed to load all assets ! {assetInfo.Error}");
CompletedProvider completedProvider = new CompletedProvider(assetInfo);
completedProvider.SetCompleted(assetInfo.Error);
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(assetInfo.Error);
return completedProvider.CreateHandle<AllAssetsHandle>();
}
string providerGUID = nameof(LoadAllAssetsAsync) + assetInfo.GUID;
ProviderBase provider = TryGetProvider(providerGUID);
ProviderOperation provider = TryGetAssetProvider(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);
provider = new AllAssetsProvider(this, providerGUID, assetInfo);
provider.InitProviderDebugInfo();
ProviderDic.Add(providerGUID, provider);
OperationSystem.StartOperation(PackageName, provider);
}
@@ -311,24 +244,30 @@ namespace YooAsset
/// </summary>
public RawFileHandle LoadRawFileAsync(AssetInfo assetInfo, uint priority)
{
if (LockLoadOperation)
{
string error = $"The load operation locked !";
YooLogger.Error(error);
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(error);
return completedProvider.CreateHandle<RawFileHandle>();
}
if (assetInfo.IsInvalid)
{
YooLogger.Error($"Failed to load raw file ! {assetInfo.Error}");
CompletedProvider completedProvider = new CompletedProvider(assetInfo);
completedProvider.SetCompleted(assetInfo.Error);
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(assetInfo.Error);
return completedProvider.CreateHandle<RawFileHandle>();
}
string providerGUID = nameof(LoadRawFileAsync) + assetInfo.GUID;
ProviderBase provider = TryGetProvider(providerGUID);
ProviderOperation provider = TryGetAssetProvider(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);
provider = new RawFileProvider(this, providerGUID, assetInfo);
provider.InitProviderDebugInfo();
ProviderDic.Add(providerGUID, provider);
OperationSystem.StartOperation(PackageName, provider);
}
@@ -336,149 +275,134 @@ namespace YooAsset
return provider.CreateHandle<RawFileHandle>();
}
internal void UnloadSubScene(string sceneName)
{
List<string> removeKeys = new List<string>();
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);
}
}
private void UnloadAllScene()
{
// 释放所有场景句柄
foreach (var valuePair in _sceneHandles)
{
valuePair.Value.ReleaseInternal();
}
_sceneHandles.Clear();
}
private void ClearSceneHandle()
{
// 释放资源包下的所有场景
if (_bundleQuery.ManifestValid())
{
string packageName = PackageName;
List<string> removeList = new List<string>();
foreach (var valuePair in _sceneHandles)
{
if (valuePair.Value.PackageName == packageName)
{
removeList.Add(valuePair.Key);
}
}
foreach (var key in removeList)
{
_sceneHandles.Remove(key);
}
}
}
internal BundleLoaderBase CreateOwnerAssetBundleLoader(AssetInfo assetInfo)
internal LoadBundleFileOperation CreateMainBundleFileLoader(AssetInfo assetInfo)
{
BundleInfo bundleInfo = _bundleQuery.GetMainBundleInfo(assetInfo);
return CreateAssetBundleLoaderInternal(bundleInfo);
return CreateBundleFileLoaderInternal(bundleInfo);
}
internal List<BundleLoaderBase> CreateDependAssetBundleLoaders(AssetInfo assetInfo)
internal List<LoadBundleFileOperation> CreateDependBundleFileLoaders(AssetInfo assetInfo)
{
BundleInfo[] depends = _bundleQuery.GetDependBundleInfos(assetInfo);
List<BundleLoaderBase> result = new List<BundleLoaderBase>(depends.Length);
foreach (var bundleInfo in depends)
BundleInfo[] bundleInfos = _bundleQuery.GetDependBundleInfos(assetInfo);
List<LoadBundleFileOperation> result = new List<LoadBundleFileOperation>(bundleInfos.Length);
foreach (var bundleInfo in bundleInfos)
{
BundleLoaderBase dependLoader = CreateAssetBundleLoaderInternal(bundleInfo);
result.Add(dependLoader);
var bundleLoader = CreateBundleFileLoaderInternal(bundleInfo);
result.Add(bundleLoader);
}
return result;
}
internal void RemoveBundleProviders(List<ProviderBase> removeList)
internal void RemoveBundleProviders(List<ProviderOperation> removeList)
{
foreach (var provider in removeList)
{
_providerDic.Remove(provider.ProviderGUID);
ProviderDic.Remove(provider.ProviderGUID);
}
}
internal bool CheckBundleDestroyed(int bundleID)
{
string bundleName = _bundleQuery.GetMainBundleName(bundleID);
var bundleFileLoader = TryGetBundleFileLoader(bundleName);
if (bundleFileLoader == null)
return true;
return bundleFileLoader.IsDestroyed;
}
internal bool HasAnyLoader()
{
return _loaderList.Count > 0;
return LoaderDic.Count > 0;
}
private BundleLoaderBase CreateAssetBundleLoaderInternal(BundleInfo bundleInfo)
private LoadBundleFileOperation CreateBundleFileLoaderInternal(BundleInfo bundleInfo)
{
// 如果加载器已经存在
string bundleName = bundleInfo.Bundle.BundleName;
BundleLoaderBase loader = TryGetAssetBundleLoader(bundleName);
if (loader != null)
return loader;
LoadBundleFileOperation loaderOperation = TryGetBundleFileLoader(bundleName);
if (loaderOperation != null)
return loaderOperation;
// 新增下载需求
if (_simulationOnEditor)
{
loader = new VirtualBundleFileLoader(this, bundleInfo);
}
else
{
#if UNITY_WEBGL
if (bundleInfo.Bundle.Buildpipeline== EDefaultBuildPipeline.RawFileBuildPipeline.ToString())
loader = new RawBundleWebLoader(this, bundleInfo);
else
loader = new AssetBundleWebLoader(this, bundleInfo);
#else
if (bundleInfo.Bundle.Buildpipeline == EDefaultBuildPipeline.RawFileBuildPipeline.ToString())
loader = new RawBundleFileLoader(this, bundleInfo);
else
loader = new AssetBundleFileLoader(this, bundleInfo);
#endif
}
_loaderList.Add(loader);
_loaderDic.Add(bundleName, loader);
return loader;
loaderOperation = new LoadBundleFileOperation(this, bundleInfo);
LoaderDic.Add(bundleName, loaderOperation);
return loaderOperation;
}
private BundleLoaderBase TryGetAssetBundleLoader(string bundleName)
private LoadBundleFileOperation TryGetBundleFileLoader(string bundleName)
{
if (_loaderDic.TryGetValue(bundleName, out BundleLoaderBase value))
if (LoaderDic.TryGetValue(bundleName, out LoadBundleFileOperation value))
return value;
else
return null;
}
private ProviderBase TryGetProvider(string providerGUID)
private ProviderOperation TryGetAssetProvider(string providerGUID)
{
if (_providerDic.TryGetValue(providerGUID, out ProviderBase value))
if (ProviderDic.TryGetValue(providerGUID, out ProviderOperation value))
return value;
else
return null;
}
private void OnSceneUnloaded(Scene scene)
{
List<SceneHandle> removeList = new List<SceneHandle>();
foreach (var sceneHandle in SceneHandles)
{
if (sceneHandle.IsValid)
{
if (sceneHandle.SceneObject == scene)
{
sceneHandle.Release();
removeList.Add(sceneHandle);
}
}
}
foreach (var sceneHandle in removeList)
{
SceneHandles.Remove(sceneHandle);
}
}
#region
internal List<DebugProviderInfo> GetDebugReportInfos()
internal List<DebugProviderInfo> GetDebugProviderInfos()
{
List<DebugProviderInfo> result = new List<DebugProviderInfo>(_providerDic.Count);
foreach (var provider in _providerDic.Values)
List<DebugProviderInfo> result = new List<DebugProviderInfo>(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.BeginTime = provider.BeginTime;
providerInfo.LoadingTime = provider.ProcessTime;
providerInfo.RefCount = provider.RefCount;
providerInfo.Status = provider.Status.ToString();
providerInfo.DependBundleInfos = new List<DebugBundleInfo>();
provider.GetBundleDebugInfos(providerInfo.DependBundleInfos);
providerInfo.DependBundles = provider.GetDebugDependBundles();
result.Add(providerInfo);
}
return result;
}
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;
bundleInfo.Status = bundleLoader.Status.ToString();
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;
}
#endregion
}
}