优化场景卸载逻辑
pull/455/head
何冠峰 2024-12-27 11:53:55 +08:00
parent 069e29ac07
commit 8944ec0e02
7 changed files with 59 additions and 116 deletions

View File

@ -112,25 +112,6 @@ namespace YooAsset
return true; return true;
} }
/// <summary>
/// 是否为主场景
/// </summary>
public bool IsMainScene()
{
if (IsValidWithWarning == false)
return false;
if (Provider is SceneProvider)
{
var temp = Provider as SceneProvider;
return temp.SceneMode == LoadSceneMode.Single;
}
else
{
throw new System.NotImplementedException();
}
}
/// <summary> /// <summary>
/// 异步卸载子场景 /// 异步卸载子场景
/// </summary> /// </summary>
@ -147,17 +128,6 @@ namespace YooAsset
return operation; return operation;
} }
// 如果是主场景
if (IsMainScene())
{
string error = $"Cannot unload main scene. Use {nameof(YooAssets.LoadSceneAsync)} method to change the main scene !";
YooLogger.Error(error);
var operation = new UnloadSceneOperation(error);
OperationSystem.StartOperation(packageName, operation);
return operation;
}
// 卸载子场景
// 注意:如果场景正在加载过程,必须等待加载完成后才可以卸载该场景。 // 注意:如果场景正在加载过程,必须等待加载完成后才可以卸载该场景。
{ {
var operation = new UnloadSceneOperation(Provider); var operation = new UnloadSceneOperation(Provider);

View File

@ -58,6 +58,9 @@ namespace YooAsset
var loaderDic = _resManager._loaderDic; var loaderDic = _resManager._loaderDic;
var providerDic = _resManager._providerDic; var providerDic = _resManager._providerDic;
// 清空所有场景句柄
_resManager._sceneHandles.Clear();
// 释放所有资源句柄 // 释放所有资源句柄
foreach (var provider in providerDic.Values) foreach (var provider in providerDic.Values)
{ {
@ -79,7 +82,6 @@ namespace YooAsset
// 清空数据 // 清空数据
providerDic.Clear(); providerDic.Clear();
loaderDic.Clear(); loaderDic.Clear();
_resManager.ClearSceneHandle();
// 注意:调用底层接口释放所有资源 // 注意:调用底层接口释放所有资源
Resources.UnloadUnusedAssets(); Resources.UnloadUnusedAssets();

View File

@ -12,7 +12,7 @@ namespace YooAsset
{ {
None, None,
CheckError, CheckError,
PrepareDone, WaitDone,
UnLoadScene, UnLoadScene,
Done, Done,
} }
@ -61,10 +61,10 @@ namespace YooAsset
return; return;
} }
_steps = ESteps.PrepareDone; _steps = ESteps.WaitDone;
} }
if (_steps == ESteps.PrepareDone) if (_steps == ESteps.WaitDone)
{ {
if (_provider.IsDone == false) if (_provider.IsDone == false)
return; return;
@ -93,14 +93,19 @@ namespace YooAsset
if (_asyncOp == null) if (_asyncOp == null)
{ {
_asyncOp = SceneManager.UnloadSceneAsync(_provider.SceneObject); _asyncOp = SceneManager.UnloadSceneAsync(_provider.SceneObject);
_provider.ResourceMgr.UnloadSubScene(_provider.SceneName); if (_asyncOp == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Unload scene failed, see the console logs !";
return;
}
} }
Progress = _asyncOp.progress; Progress = _asyncOp.progress;
if (_asyncOp.isDone == false) if (_asyncOp.isDone == false)
return; return;
_provider.ResourceMgr.TryUnloadUnusedAsset(_provider.MainAssetInfo);
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Succeed; Status = EOperationStatus.Succeed;
} }

View File

@ -20,11 +20,6 @@ namespace YooAsset
/// </summary> /// </summary>
public string ProviderGUID { private set; get; } public string ProviderGUID { private set; get; }
/// <summary>
/// 所属资源系统
/// </summary>
public ResourceManager ResourceMgr { private set; get; }
/// <summary> /// <summary>
/// 资源信息 /// 资源信息
/// </summary> /// </summary>
@ -79,7 +74,6 @@ namespace YooAsset
public ProviderOperation(ResourceManager manager, string providerGUID, AssetInfo assetInfo) public ProviderOperation(ResourceManager manager, string providerGUID, AssetInfo assetInfo)
{ {
ResourceMgr = manager;
ProviderGUID = providerGUID; ProviderGUID = providerGUID;
MainAssetInfo = assetInfo; MainAssetInfo = assetInfo;

View File

@ -12,17 +12,6 @@ namespace YooAsset
private bool _suspendLoad; private bool _suspendLoad;
private FSLoadSceneOperation _loadSceneOp; private FSLoadSceneOperation _loadSceneOp;
/// <summary>
/// 场景加载模式
/// </summary>
public LoadSceneMode SceneMode
{
get
{
return _loadParams.loadSceneMode;
}
}
public SceneProvider(ResourceManager manager, string providerGUID, AssetInfo assetInfo, LoadSceneParameters loadParams, bool suspendLoad) : base(manager, providerGUID, assetInfo) public SceneProvider(ResourceManager manager, string providerGUID, AssetInfo assetInfo, LoadSceneParameters loadParams, bool suspendLoad) : base(manager, providerGUID, assetInfo)
{ {
_loadParams = loadParams; _loadParams = loadParams;

View File

@ -9,12 +9,10 @@ namespace YooAsset
{ {
internal class ResourceManager internal class ResourceManager
{ {
// 全局场景句柄集合
private readonly static Dictionary<string, SceneHandle> _sceneHandles = new Dictionary<string, SceneHandle>(100);
private static long _sceneCreateCount = 0;
internal readonly Dictionary<string, ProviderOperation> _providerDic = new Dictionary<string, ProviderOperation>(5000); internal readonly Dictionary<string, ProviderOperation> _providerDic = new Dictionary<string, ProviderOperation>(5000);
internal readonly Dictionary<string, LoadBundleFileOperation> _loaderDic = new Dictionary<string, LoadBundleFileOperation>(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; private IBundleQuery _bundleQuery;
/// <summary> /// <summary>
@ -34,6 +32,15 @@ namespace YooAsset
public void Initialize(InitializeParameters initializeParameters, IBundleQuery bundleServices) public void Initialize(InitializeParameters initializeParameters, IBundleQuery bundleServices)
{ {
_bundleQuery = bundleServices; _bundleQuery = bundleServices;
SceneManager.sceneUnloaded += OnSceneUnloaded;
}
/// <summary>
/// 销毁管理器
/// </summary>
public void Destroy()
{
SceneManager.sceneUnloaded -= OnSceneUnloaded;
} }
/// <summary> /// <summary>
@ -93,14 +100,8 @@ namespace YooAsset
return completedProvider.CreateHandle<SceneHandle>(); return completedProvider.CreateHandle<SceneHandle>();
} }
// 如果加载的是主场景,则卸载所有缓存的场景
if (loadSceneParams.loadSceneMode == LoadSceneMode.Single)
{
UnloadAllScene();
}
// 注意同一个场景的ProviderGUID每次加载都会变化 // 注意同一个场景的ProviderGUID每次加载都会变化
string providerGUID = $"{assetInfo.GUID}-{++_sceneCreateCount}"; string providerGUID = $"{assetInfo.GUID}-{++_sceneCreateIndex}";
ProviderOperation provider; ProviderOperation provider;
{ {
provider = new SceneProvider(this, providerGUID, assetInfo, loadSceneParams, suspendLoad); provider = new SceneProvider(this, providerGUID, assetInfo, loadSceneParams, suspendLoad);
@ -112,7 +113,7 @@ namespace YooAsset
provider.Priority = priority; provider.Priority = priority;
var handle = provider.CreateHandle<SceneHandle>(); var handle = provider.CreateHandle<SceneHandle>();
handle.PackageName = PackageName; handle.PackageName = PackageName;
_sceneHandles.Add(providerGUID, handle); _sceneHandles.Add(handle);
return handle; return handle;
} }
@ -224,56 +225,6 @@ namespace YooAsset
return provider.CreateHandle<RawFileHandle>(); 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);
}
}
internal void UnloadAllScene()
{
// 释放所有场景句柄
foreach (var valuePair in _sceneHandles)
{
valuePair.Value.ReleaseInternal();
}
_sceneHandles.Clear();
}
internal 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 LoadBundleFileOperation CreateMainBundleFileLoader(AssetInfo assetInfo) internal LoadBundleFileOperation CreateMainBundleFileLoader(AssetInfo assetInfo)
{ {
BundleInfo bundleInfo = _bundleQuery.GetMainBundleInfo(assetInfo); BundleInfo bundleInfo = _bundleQuery.GetMainBundleInfo(assetInfo);
@ -330,6 +281,25 @@ namespace YooAsset
else else
return null; 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.ReleaseInternal();
removeList.Add(sceneHandle);
}
}
}
foreach (var sceneHandle in removeList)
{
_sceneHandles.Remove(sceneHandle);
}
}
#region 调试信息 #region 调试信息
internal List<DebugProviderInfo> GetDebugReportInfos() internal List<DebugProviderInfo> GetDebugReportInfos()

View File

@ -57,7 +57,13 @@ namespace YooAsset
_initializeError = string.Empty; _initializeError = string.Empty;
_initializeStatus = EOperationStatus.None; _initializeStatus = EOperationStatus.None;
_resourceManager = null; // 销毁资源管理器
if (_resourceManager != null)
{
_resourceManager.Destroy();
_resourceManager = null;
}
_bundleQuery = null; _bundleQuery = null;
_playModeImpl = null; _playModeImpl = null;
} }
@ -74,6 +80,13 @@ namespace YooAsset
// 检测初始化参数合法性 // 检测初始化参数合法性
CheckInitializeParameters(parameters); CheckInitializeParameters(parameters);
// 销毁资源管理器
if (_resourceManager != null)
{
_resourceManager.Destroy();
_resourceManager = null;
}
// 创建资源管理器 // 创建资源管理器
InitializationOperation initializeOperation; InitializationOperation initializeOperation;
_resourceManager = new ResourceManager(PackageName); _resourceManager = new ResourceManager(PackageName);