diff --git a/Assets/YooAsset/Runtime/AssetSystem/AssetSystem.cs b/Assets/YooAsset/Runtime/AssetSystem/AssetSystem.cs index 2745f6a..6259d92 100644 --- a/Assets/YooAsset/Runtime/AssetSystem/AssetSystem.cs +++ b/Assets/YooAsset/Runtime/AssetSystem/AssetSystem.cs @@ -68,40 +68,6 @@ namespace YooAsset loadingCount++; } } - - // 注意:需要立刻卸载场景 - if (SimulationOnEditor) - { - for (int i = _providers.Count - 1; i >= 0; i--) - { - AssetProviderBase provider = _providers[i]; - if (provider.IsSceneProvider() && provider.CanDestroy()) - { - provider.Destory(); - _providers.RemoveAt(i); - } - } - } - else - { - for (int i = _loaders.Count - 1; i >= 0; i--) - { - BundleFileLoader loader = _loaders[i]; - if (loader.IsSceneLoader()) - { - loader.TryDestroyAllProviders(); - } - } - for (int i = _loaders.Count - 1; i >= 0; i--) - { - BundleFileLoader loader = _loaders[i]; - if (loader.IsSceneLoader() && loader.CanDestroy()) - { - loader.Destroy(false); - _loaders.RemoveAt(i); - } - } - } } /// @@ -160,19 +126,19 @@ namespace YooAsset Resources.UnloadUnusedAssets(); } + /// /// 异步加载场景 /// - /// 场景名称 - public static SceneOperationHandle LoadSceneAsync(string scenePath, LoadSceneMode mode, bool activateOnLoad) + public static SceneOperationHandle LoadSceneAsync(string scenePath, LoadSceneMode sceneMode, bool activateOnLoad, int priority) { AssetProviderBase provider = TryGetAssetProvider(scenePath); if (provider == null) { if (SimulationOnEditor) - provider = new DatabaseSceneProvider(scenePath, mode, activateOnLoad); + provider = new DatabaseSceneProvider(scenePath, sceneMode, activateOnLoad, priority); else - provider = new BundledSceneProvider(scenePath, mode, activateOnLoad); + provider = new BundledSceneProvider(scenePath, sceneMode, activateOnLoad, priority); _providers.Add(provider); } return provider.CreateHandle() as SceneOperationHandle; @@ -181,8 +147,6 @@ namespace YooAsset /// /// 异步加载资源对象 /// - /// 资源路径 - /// 资源类型 public static AssetOperationHandle LoadAssetAsync(string assetPath, System.Type assetType) { AssetProviderBase provider = TryGetAssetProvider(assetPath); @@ -200,9 +164,7 @@ namespace YooAsset /// /// 异步加载所有子资源对象 /// - /// 资源路径 - /// 资源类型、 - public static AssetOperationHandle LoadSubAssetsAsync(string assetPath, System.Type assetType) + public static SubAssetsOperationHandle LoadSubAssetsAsync(string assetPath, System.Type assetType) { AssetProviderBase provider = TryGetAssetProvider(assetPath); if (provider == null) @@ -213,7 +175,7 @@ namespace YooAsset provider = new BundledSubAssetsProvider(assetPath, assetType); _providers.Add(provider); } - return provider.CreateHandle() as AssetOperationHandle; + return provider.CreateHandle() as SubAssetsOperationHandle; } diff --git a/Assets/YooAsset/Runtime/AssetSystem/Operations/AssetOperationHandle.cs b/Assets/YooAsset/Runtime/AssetSystem/Operations/AssetOperationHandle.cs index a0363be..858a3cd 100644 --- a/Assets/YooAsset/Runtime/AssetSystem/Operations/AssetOperationHandle.cs +++ b/Assets/YooAsset/Runtime/AssetSystem/Operations/AssetOperationHandle.cs @@ -76,5 +76,13 @@ namespace YooAsset return; _provider.WaitForAsyncComplete(); } + + /// + /// 释放资源句柄 + /// + public void Release() + { + this.ReleaseInternal(); + } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/AssetSystem/Operations/OperationHandleBase.cs b/Assets/YooAsset/Runtime/AssetSystem/Operations/OperationHandleBase.cs index 1014400..c91edfb 100644 --- a/Assets/YooAsset/Runtime/AssetSystem/Operations/OperationHandleBase.cs +++ b/Assets/YooAsset/Runtime/AssetSystem/Operations/OperationHandleBase.cs @@ -70,7 +70,7 @@ namespace YooAsset /// /// 释放句柄 /// - public void Release() + internal void ReleaseInternal() { if (IsValid == false) return; diff --git a/Assets/YooAsset/Runtime/AssetSystem/Operations/SceneOperationHandle.cs b/Assets/YooAsset/Runtime/AssetSystem/Operations/SceneOperationHandle.cs index c2092a2..a3102c6 100644 --- a/Assets/YooAsset/Runtime/AssetSystem/Operations/SceneOperationHandle.cs +++ b/Assets/YooAsset/Runtime/AssetSystem/Operations/SceneOperationHandle.cs @@ -1,8 +1,114 @@ - +using UnityEngine; +using UnityEngine.SceneManagement; + namespace YooAsset { public class SceneOperationHandle : OperationHandleBase { + /// + /// 场景卸载异步操作类 + /// + public class UnloadSceneOperation : AsyncOperationBase + { + private enum EFlag + { + Normal, + Error, + Skip, + } + private enum ESteps + { + None, + UnLoad, + Checking, + Done, + } + + private readonly EFlag _flag; + private ESteps _steps = ESteps.None; + private Scene _scene; + private AsyncOperation _asyncOp; + + /// + /// 场景卸载进度 + /// + public float Progress + { + get + { + if (_asyncOp == null) + return 0; + return _asyncOp.progress; + } + } + + internal UnloadSceneOperation() + { + _flag = EFlag.Skip; + } + internal UnloadSceneOperation(string error) + { + _flag = EFlag.Error; + Error = error; + } + internal UnloadSceneOperation(Scene scene) + { + _flag = EFlag.Normal; + _scene = scene; + } + internal override void Start() + { + if (_flag == EFlag.Normal) + { + _steps = ESteps.UnLoad; + } + else if (_flag == EFlag.Skip) + { + _steps = ESteps.Done; + Status = EOperationStatus.Succeed; + } + else if (_flag == EFlag.Error) + { + _steps = ESteps.Done; + Status = EOperationStatus.Failed; + } + else + { + throw new System.NotImplementedException(_flag.ToString()); + } + } + internal override void Update() + { + if (_steps == ESteps.None || _steps == ESteps.Done) + return; + + if (_steps == ESteps.UnLoad) + { + if (_scene.IsValid() && _scene.isLoaded) + { + _asyncOp = SceneManager.UnloadSceneAsync(_scene); + _steps = ESteps.Checking; + } + else + { + Error = "Scene is invalid or is not loaded."; + _steps = ESteps.Done; + Status = EOperationStatus.Failed; + } + } + + if (_steps == ESteps.Checking) + { + if (_asyncOp.isDone == false) + return; + + _steps = ESteps.Done; + Status = EOperationStatus.Succeed; + } + } + } + + private System.Action _callback; internal SceneOperationHandle(AssetProviderBase provider) : base(provider) @@ -41,13 +147,13 @@ namespace YooAsset /// /// 场景对象 /// - public UnityEngine.SceneManagement.Scene Scene + public Scene SceneObject { get { if (IsValid == false) - return new UnityEngine.SceneManagement.Scene(); - return _provider.Scene; + return new Scene(); + return _provider.SceneObject; } } @@ -59,15 +165,79 @@ namespace YooAsset if (IsValid == false) return false; - if (Scene.IsValid() && Scene.isLoaded) + if (SceneObject.IsValid() && SceneObject.isLoaded) { - return UnityEngine.SceneManagement.SceneManager.SetActiveScene(Scene); + return SceneManager.SetActiveScene(SceneObject); } else { - YooLogger.Warning($"Scene is invalid or not loaded : {Scene.name}"); + YooLogger.Warning($"Scene is invalid or not loaded : {SceneObject.name}"); return false; } } + + /// + /// 异步卸载场景 + /// + public UnloadSceneOperation UnloadAsync() + { + if (IsValid == false) + { + string error = $"{nameof(SceneOperationHandle)} is invalid."; + var operation = new UnloadSceneOperation(error); + OperationSystem.ProcessOperaiton(operation); + return operation; + } + + AssetProviderBase provider = _provider; + + // 释放场景句柄 + ReleaseInternal(); + + // 卸载未被使用的资源(包括场景) + AssetSystem.UnloadUnusedAssets(); + + // 返回场景卸载异步操作类 + if (provider.IsDestroyed == false) + { + YooLogger.Warning($"Scene can not unload. The provider not destroyed : {provider.AssetPath}"); + var operation = new UnloadSceneOperation(); + 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(AssetProviderBase provider) + { + if (provider is DatabaseSceneProvider) + { + 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(); + } + } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/AssetSystem/Operations/SubAssetsOperationHandle.cs b/Assets/YooAsset/Runtime/AssetSystem/Operations/SubAssetsOperationHandle.cs new file mode 100644 index 0000000..82f30bd --- /dev/null +++ b/Assets/YooAsset/Runtime/AssetSystem/Operations/SubAssetsOperationHandle.cs @@ -0,0 +1,92 @@ + +namespace YooAsset +{ + public class SubAssetsOperationHandle : OperationHandleBase + { + private System.Action _callback; + + internal SubAssetsOperationHandle(AssetProviderBase provider) : base(provider) + { + } + internal override void InvokeCallback() + { + if (IsValid) + { + _callback?.Invoke(this); + } + } + + /// + /// 完成委托 + /// + public event System.Action Completed + { + add + { + if (IsValid == false) + throw new System.Exception($"{nameof(SubAssetsOperationHandle)} is invalid"); + if (_provider.IsDone) + value.Invoke(this); + else + _callback += value; + } + remove + { + if (IsValid == false) + throw new System.Exception($"{nameof(SubAssetsOperationHandle)} is invalid"); + _callback -= value; + } + } + + /// + /// 子资源对象集合 + /// + public UnityEngine.Object[] AllAssetObjects + { + get + { + if (IsValid == false) + return null; + return _provider.AllAssets; + } + } + + /// + /// 获取子资源对象 + /// + /// 子资源对象类型 + /// 子资源对象名称 + public TObject GetSubAssetObject(string assetName) where TObject : UnityEngine.Object + { + if (IsValid == false) + return null; + + foreach (var asset in _provider.AllAssets) + { + if (asset.name == assetName) + return asset as TObject; + } + + YooLogger.Warning($"Not found sub asset {assetName} in {_provider.AssetPath}"); + return null; + } + + /// + /// 等待异步执行完毕 + /// + public void WaitForAsyncComplete() + { + if (IsValid == false) + return; + _provider.WaitForAsyncComplete(); + } + + /// + /// 释放资源句柄 + /// + public void Release() + { + this.ReleaseInternal(); + } + } +} \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/AssetSystem/Operations/SubAssetsOperationHandle.cs.meta b/Assets/YooAsset/Runtime/AssetSystem/Operations/SubAssetsOperationHandle.cs.meta new file mode 100644 index 0000000..5752721 --- /dev/null +++ b/Assets/YooAsset/Runtime/AssetSystem/Operations/SubAssetsOperationHandle.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 76b148be04a698e45a54dd85e64969dd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/YooAsset/Runtime/AssetSystem/Provider/AssetProviderBase.cs b/Assets/YooAsset/Runtime/AssetSystem/Provider/AssetProviderBase.cs index d0843e2..ebd2233 100644 --- a/Assets/YooAsset/Runtime/AssetSystem/Provider/AssetProviderBase.cs +++ b/Assets/YooAsset/Runtime/AssetSystem/Provider/AssetProviderBase.cs @@ -43,7 +43,7 @@ namespace YooAsset /// /// 获取的场景对象 /// - public UnityEngine.SceneManagement.Scene Scene { protected set; get; } + public UnityEngine.SceneManagement.Scene SceneObject { protected set; get; } /// @@ -108,6 +108,17 @@ namespace YooAsset IsDestroyed = true; } + /// + /// 是否可以销毁 + /// + public bool CanDestroy() + { + if (IsDone == false) + return false; + + return RefCount <= 0; + } + /// /// 创建操作句柄 /// @@ -120,6 +131,8 @@ namespace YooAsset OperationHandleBase handle; if (IsSceneProvider()) handle = new SceneOperationHandle(this); + else if (IsSubAssetsProvider()) + handle = new SubAssetsOperationHandle(this); else handle = new AssetOperationHandle(this); @@ -142,17 +155,6 @@ namespace YooAsset RefCount--; } - /// - /// 是否可以销毁 - /// - public bool CanDestroy() - { - if (IsDone == false) - return false; - - return RefCount <= 0; - } - /// /// 是否为场景提供者 /// @@ -164,6 +166,17 @@ namespace YooAsset return false; } + /// + /// 是否为子资源对象提供者 + /// + public bool IsSubAssetsProvider() + { + if (this is BundledSubAssetsProvider || this is DatabaseSubAssetsProvider) + return true; + else + return false; + } + /// /// 等待异步执行完毕 /// diff --git a/Assets/YooAsset/Runtime/AssetSystem/Provider/BundledSceneProvider.cs b/Assets/YooAsset/Runtime/AssetSystem/Provider/BundledSceneProvider.cs index 2c7240f..7e8ec5e 100644 --- a/Assets/YooAsset/Runtime/AssetSystem/Provider/BundledSceneProvider.cs +++ b/Assets/YooAsset/Runtime/AssetSystem/Provider/BundledSceneProvider.cs @@ -7,8 +7,9 @@ namespace YooAsset { internal sealed class BundledSceneProvider : BundledProvider { - private readonly LoadSceneMode _sceneMode; + public readonly LoadSceneMode SceneMode; private readonly bool _activateOnLoad; + private readonly int _priority; private AsyncOperation _asyncOp; public override float Progress { @@ -20,11 +21,12 @@ namespace YooAsset } } - public BundledSceneProvider(string scenePath, LoadSceneMode sceneMode, bool activateOnLoad) + public BundledSceneProvider(string scenePath, LoadSceneMode sceneMode, bool activateOnLoad, int priority) : base(scenePath, null) { - _sceneMode = sceneMode; + SceneMode = sceneMode; _activateOnLoad = activateOnLoad; + _priority = priority; } public override void Update() { @@ -58,10 +60,11 @@ namespace YooAsset // 2. 加载场景 if (Status == EStatus.Loading) { - _asyncOp = SceneManager.LoadSceneAsync(AssetName, _sceneMode); + _asyncOp = SceneManager.LoadSceneAsync(AssetName, SceneMode); if (_asyncOp != null) { _asyncOp.allowSceneActivation = true; + _asyncOp.priority = _priority; Status = EStatus.Checking; } else @@ -77,25 +80,14 @@ namespace YooAsset { if (_asyncOp.isDone) { - Scene = SceneManager.GetSceneByName(AssetName); - if (_activateOnLoad) - SceneManager.SetActiveScene(Scene); + SceneObject = SceneManager.GetSceneByName(AssetName); + if (SceneObject.IsValid() && _activateOnLoad) + SceneManager.SetActiveScene(SceneObject); - Status = Scene.IsValid() ? EStatus.Success : EStatus.Fail; + Status = SceneObject.IsValid() ? EStatus.Success : EStatus.Fail; InvokeCompletion(); } } } - public override void Destory() - { - base.Destory(); - - // 卸载附加场景(异步方式卸载) - if (_sceneMode == LoadSceneMode.Additive) - { - if (Scene.IsValid() && Scene.isLoaded) - SceneManager.UnloadSceneAsync(Scene); - } - } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/AssetSystem/Provider/DatabaseSceneProvider.cs b/Assets/YooAsset/Runtime/AssetSystem/Provider/DatabaseSceneProvider.cs index 57de498..51f3007 100644 --- a/Assets/YooAsset/Runtime/AssetSystem/Provider/DatabaseSceneProvider.cs +++ b/Assets/YooAsset/Runtime/AssetSystem/Provider/DatabaseSceneProvider.cs @@ -5,8 +5,9 @@ namespace YooAsset { internal sealed class DatabaseSceneProvider : AssetProviderBase { - private readonly LoadSceneMode _sceneMode; + public readonly LoadSceneMode SceneMode; private readonly bool _activateOnLoad; + private readonly int _priority; private AsyncOperation _asyncOp; public override float Progress { @@ -18,11 +19,12 @@ namespace YooAsset } } - public DatabaseSceneProvider(string scenePath, LoadSceneMode sceneMode, bool activateOnLoad) + public DatabaseSceneProvider(string scenePath, LoadSceneMode sceneMode, bool activateOnLoad, int priority) : base(scenePath, null) { - _sceneMode = sceneMode; + SceneMode = sceneMode; _activateOnLoad = activateOnLoad; + _priority = priority; } public override void Update() { @@ -39,11 +41,12 @@ namespace YooAsset if (Status == EStatus.Loading) { LoadSceneParameters loadSceneParameters = new LoadSceneParameters(); - loadSceneParameters.loadSceneMode = _sceneMode; + loadSceneParameters.loadSceneMode = SceneMode; _asyncOp = UnityEditor.SceneManagement.EditorSceneManager.LoadSceneAsyncInPlayMode(AssetPath, loadSceneParameters); if (_asyncOp != null) { _asyncOp.allowSceneActivation = true; + _asyncOp.priority = _priority; Status = EStatus.Checking; } else @@ -59,27 +62,14 @@ namespace YooAsset { if (_asyncOp.isDone) { - Scene = SceneManager.GetSceneAt(SceneManager.sceneCount - 1); - if (_activateOnLoad) - SceneManager.SetActiveScene(Scene); + SceneObject = SceneManager.GetSceneAt(SceneManager.sceneCount - 1); + if (SceneObject.IsValid() && _activateOnLoad) + SceneManager.SetActiveScene(SceneObject); - Status = Scene.IsValid() ? EStatus.Success : EStatus.Fail; + Status = SceneObject.IsValid() ? EStatus.Success : EStatus.Fail; InvokeCompletion(); } } -#endif - } - public override void Destory() - { -#if UNITY_EDITOR - base.Destory(); - - // 卸载附加场景(异步方式卸载) - if (_sceneMode == LoadSceneMode.Additive) - { - if (Scene.IsValid() && Scene.isLoaded) - SceneManager.UnloadSceneAsync(Scene); - } #endif } } diff --git a/Assets/YooAsset/Runtime/YooAssets.cs b/Assets/YooAsset/Runtime/YooAssets.cs index 548abb6..c83f969 100644 --- a/Assets/YooAsset/Runtime/YooAssets.cs +++ b/Assets/YooAsset/Runtime/YooAssets.cs @@ -289,17 +289,18 @@ namespace YooAsset AssetSystem.GetDebugReport(report); } - #region 场景接口 + #region 场景加载接口 /// /// 异步加载场景 /// /// 场景对象相对路径 - /// 场景加载模式 + /// 场景加载模式 /// 加载完毕时是否主动激活 - public static SceneOperationHandle LoadSceneAsync(string location, LoadSceneMode mode, bool activateOnLoad) + /// 优先级 + public static SceneOperationHandle LoadSceneAsync(string location, LoadSceneMode sceneMode = LoadSceneMode.Single, bool activateOnLoad = true, int priority = 100) { string scenePath = ConvertLocationToAssetPath(location); - var handle = AssetSystem.LoadSceneAsync(scenePath, mode, activateOnLoad); + var handle = AssetSystem.LoadSceneAsync(scenePath, sceneMode, activateOnLoad, priority); return handle; } #endregion @@ -330,7 +331,7 @@ namespace YooAsset /// /// 资源类型 /// 资源对象相对路径 - public static AssetOperationHandle LoadSubAssetsSync(string location) + public static SubAssetsOperationHandle LoadSubAssetsSync(string location) { return LoadSubAssetsInternal(location, typeof(TObject), true); } @@ -340,7 +341,7 @@ namespace YooAsset /// /// 资源对象相对路径 /// 子对象类型 - public static AssetOperationHandle LoadSubAssetsSync(string location, System.Type type) + public static SubAssetsOperationHandle LoadSubAssetsSync(string location, System.Type type) { return LoadSubAssetsInternal(location, type, true); } @@ -371,7 +372,7 @@ namespace YooAsset /// /// 资源类型 /// 资源对象相对路径 - public static AssetOperationHandle LoadSubAssetsAsync(string location) + public static SubAssetsOperationHandle LoadSubAssetsAsync(string location) { return LoadSubAssetsInternal(location, typeof(TObject), false); } @@ -381,7 +382,7 @@ namespace YooAsset /// /// 资源对象相对路径 /// 子对象类型 - public static AssetOperationHandle LoadSubAssetsAsync(string location, System.Type type) + public static SubAssetsOperationHandle LoadSubAssetsAsync(string location, System.Type type) { return LoadSubAssetsInternal(location, type, false); } @@ -395,7 +396,7 @@ namespace YooAsset handle.WaitForAsyncComplete(); return handle; } - private static AssetOperationHandle LoadSubAssetsInternal(string location, System.Type assetType, bool waitForAsyncComplete) + private static SubAssetsOperationHandle LoadSubAssetsInternal(string location, System.Type assetType, bool waitForAsyncComplete) { string assetPath = ConvertLocationToAssetPath(location); var handle = AssetSystem.LoadSubAssetsAsync(assetPath, assetType);