diff --git a/Assets/YooAsset/Runtime/AssetSystem/AssetSystem.cs b/Assets/YooAsset/Runtime/AssetSystem/AssetSystem.cs index dfde138..629123e 100644 --- a/Assets/YooAsset/Runtime/AssetSystem/AssetSystem.cs +++ b/Assets/YooAsset/Runtime/AssetSystem/AssetSystem.cs @@ -10,6 +10,7 @@ namespace YooAsset { private static readonly List _loaders = new List(1000); private static readonly List _providers = new List(1000); + private static readonly Dictionary _sceneHandles = new Dictionary(100); /// /// 在编辑器下模拟运行 @@ -132,6 +133,14 @@ namespace YooAsset /// public static SceneOperationHandle LoadSceneAsync(string scenePath, LoadSceneMode sceneMode, bool activateOnLoad, int priority) { + // 注意:场景句柄永远保持唯一 + if (_sceneHandles.ContainsKey(scenePath)) + return _sceneHandles[scenePath]; + + // 如果加载的是主场景,则卸载所有缓存的场景 + if (sceneMode == LoadSceneMode.Single) + UnloadAllScene(); + ProviderBase provider = TryGetProvider(scenePath); if (provider == null) { @@ -141,7 +150,9 @@ namespace YooAsset provider = new BundledSceneProvider(scenePath, sceneMode, activateOnLoad, priority); _providers.Add(provider); } - return provider.CreateHandle() as SceneOperationHandle; + var handle = provider.CreateHandle() as SceneOperationHandle; + _sceneHandles.Add(scenePath, handle); + return handle; } /// @@ -179,6 +190,48 @@ namespace YooAsset } + internal static void UnloadSubScene(ProviderBase provider) + { + string scenePath = provider.AssetPath; + if (_sceneHandles.ContainsKey(scenePath) == false) + throw new Exception("Should never get here !"); + + // 释放子场景句柄 + _sceneHandles[scenePath].ReleaseInternal(); + _sceneHandles.Remove(scenePath); + + // 卸载未被使用的资源(包括场景) + AssetSystem.UnloadUnusedAssets(); + + // 检验子场景是否销毁 + if (provider.IsDestroyed == false) + { + throw new Exception("Should never get here !"); + } + } + internal static void UnloadAllScene() + { + // 释放所有场景句柄 + foreach (var valuePair in _sceneHandles) + { + valuePair.Value.ReleaseInternal(); + } + _sceneHandles.Clear(); + + // 卸载未被使用的资源(包括场景) + AssetSystem.UnloadUnusedAssets(); + + // 检验所有场景是否销毁 + foreach (var provider in _providers) + { + if (provider.IsSceneProvider()) + { + if (provider.IsDestroyed == false) + throw new Exception("Should never get here !"); + } + } + } + internal static AssetBundleLoaderBase CreateOwnerAssetBundleLoader(string assetPath) { string bundleName = BundleServices.GetBundleName(assetPath); @@ -254,6 +307,7 @@ namespace YooAsset return provider; } + #region 调试专属方法 internal static void GetDebugReport(DebugReport report) { diff --git a/Assets/YooAsset/Runtime/AssetSystem/Handles/AssetOperationHandle.cs b/Assets/YooAsset/Runtime/AssetSystem/Handles/AssetOperationHandle.cs index 99e6054..b9e1b01 100644 --- a/Assets/YooAsset/Runtime/AssetSystem/Handles/AssetOperationHandle.cs +++ b/Assets/YooAsset/Runtime/AssetSystem/Handles/AssetOperationHandle.cs @@ -2,7 +2,7 @@ namespace YooAsset { - public class AssetOperationHandle : OperationHandleBase + public sealed class AssetOperationHandle : OperationHandleBase { private System.Action _callback; diff --git a/Assets/YooAsset/Runtime/AssetSystem/Handles/OperationHandleBase.cs b/Assets/YooAsset/Runtime/AssetSystem/Handles/OperationHandleBase.cs index 9ead80f..6e8ab0f 100644 --- a/Assets/YooAsset/Runtime/AssetSystem/Handles/OperationHandleBase.cs +++ b/Assets/YooAsset/Runtime/AssetSystem/Handles/OperationHandleBase.cs @@ -4,11 +4,13 @@ namespace YooAsset { public abstract class OperationHandleBase : IEnumerator { + private readonly string _cachedAssetPath; internal ProviderBase _provider { private set; get; } - + internal OperationHandleBase(ProviderBase provider) { _provider = provider; + _cachedAssetPath = provider.AssetPath; } internal abstract void InvokeCallback(); @@ -63,7 +65,18 @@ namespace YooAsset { get { - return _provider != null && _provider.IsDestroyed == false; + if (_provider != null && _provider.IsDestroyed == false) + { + return true; + } + else + { + if (_provider == null) + YooLogger.Warning($"Operation handle is released : {_cachedAssetPath}"); + else if (_provider.IsDestroyed) + YooLogger.Warning($"Provider is destroyed : {_cachedAssetPath}"); + return false; + } } } diff --git a/Assets/YooAsset/Runtime/AssetSystem/Handles/SceneOperationHandle.cs b/Assets/YooAsset/Runtime/AssetSystem/Handles/SceneOperationHandle.cs index 5d0ed59..ce4bb87 100644 --- a/Assets/YooAsset/Runtime/AssetSystem/Handles/SceneOperationHandle.cs +++ b/Assets/YooAsset/Runtime/AssetSystem/Handles/SceneOperationHandle.cs @@ -69,10 +69,35 @@ namespace YooAsset } /// - /// 异步卸载场景 + /// 是否为主场景 + /// + public bool IsMainScene() + { + if (IsValid == false) + return false; + + if (_provider is DatabaseSceneProvider) + { + var temp = _provider as DatabaseSceneProvider; + return temp.SceneMode == LoadSceneMode.Single; + } + else if (_provider is BundledSceneProvider) + { + var temp = _provider as BundledSceneProvider; + return temp.SceneMode == LoadSceneMode.Single; + } + else + { + throw new System.NotImplementedException(); + } + } + + /// + /// 异步卸载子场景 /// public UnloadSceneOperation UnloadAsync() { + // 如果句柄无效 if (IsValid == false) { string error = $"{nameof(SceneOperationHandle)} is invalid."; @@ -81,54 +106,23 @@ namespace YooAsset return operation; } - ProviderBase provider = _provider; - - // 释放场景句柄 - ReleaseInternal(); - - // 卸载未被使用的资源(包括场景) - AssetSystem.UnloadUnusedAssets(); - - // 返回场景卸载异步操作类 - if (provider.IsDestroyed == false) + // 如果是主场景 + if (IsMainScene()) { - YooLogger.Warning($"Scene can not unload. The provider not destroyed : {provider.AssetPath}"); - var operation = new UnloadSceneOperation(); + 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.ProcessOperaiton(operation); return operation; } - else - { - if (IsAdditiveScene(provider)) - { - var operation = new UnloadSceneOperation(provider.SceneObject); - OperationSystem.ProcessOperaiton(operation); - return operation; - } - else - { - var operation = new UnloadSceneOperation(); - OperationSystem.ProcessOperaiton(operation); - return operation; - } - } - } - private bool IsAdditiveScene(ProviderBase provider) - { - if (provider is DatabaseSceneProvider) + // 卸载子场景 + Scene sceneObject = SceneObject; + AssetSystem.UnloadSubScene(_provider); { - var temp = provider as DatabaseSceneProvider; - return temp.SceneMode == LoadSceneMode.Additive; - } - else if (provider is BundledSceneProvider) - { - var temp = provider as BundledSceneProvider; - return temp.SceneMode == LoadSceneMode.Additive; - } - else - { - throw new System.NotImplementedException(); + var operation = new UnloadSceneOperation(sceneObject); + OperationSystem.ProcessOperaiton(operation); + return operation; } } } diff --git a/Assets/YooAsset/Runtime/AssetSystem/Handles/SubAssetsOperationHandle.cs b/Assets/YooAsset/Runtime/AssetSystem/Handles/SubAssetsOperationHandle.cs index 8d80f13..f3d3011 100644 --- a/Assets/YooAsset/Runtime/AssetSystem/Handles/SubAssetsOperationHandle.cs +++ b/Assets/YooAsset/Runtime/AssetSystem/Handles/SubAssetsOperationHandle.cs @@ -1,7 +1,7 @@  namespace YooAsset { - public class SubAssetsOperationHandle : OperationHandleBase + public sealed class SubAssetsOperationHandle : OperationHandleBase { private System.Action _callback; diff --git a/Assets/YooAsset/Runtime/AssetSystem/Operations/InstantiateOperation.cs b/Assets/YooAsset/Runtime/AssetSystem/Operations/InstantiateOperation.cs index eaa6b16..9265be6 100644 --- a/Assets/YooAsset/Runtime/AssetSystem/Operations/InstantiateOperation.cs +++ b/Assets/YooAsset/Runtime/AssetSystem/Operations/InstantiateOperation.cs @@ -48,12 +48,15 @@ namespace YooAsset _steps = ESteps.Done; Status = EOperationStatus.Failed; Error = $"{nameof(AssetOperationHandle)} is invalid."; + return; } + if (_handle.AssetObject == null) { _steps = ESteps.Done; Status = EOperationStatus.Failed; Error = $"{nameof(AssetOperationHandle.AssetObject)} is null."; + return; } if(_setPositionRotation) diff --git a/Assets/YooAsset/Runtime/AssetSystem/Operations/UnloadSceneOperation.cs b/Assets/YooAsset/Runtime/AssetSystem/Operations/UnloadSceneOperation.cs index 909e28b..a1e453d 100644 --- a/Assets/YooAsset/Runtime/AssetSystem/Operations/UnloadSceneOperation.cs +++ b/Assets/YooAsset/Runtime/AssetSystem/Operations/UnloadSceneOperation.cs @@ -12,7 +12,6 @@ namespace YooAsset { Normal, Error, - Skip, } private enum ESteps { @@ -40,10 +39,6 @@ namespace YooAsset } } - internal UnloadSceneOperation() - { - _flag = EFlag.Skip; - } internal UnloadSceneOperation(string error) { _flag = EFlag.Error; @@ -60,11 +55,6 @@ namespace YooAsset { _steps = ESteps.UnLoad; } - else if (_flag == EFlag.Skip) - { - _steps = ESteps.Done; - Status = EOperationStatus.Succeed; - } else if (_flag == EFlag.Error) { _steps = ESteps.Done;