Update AssetSystem

pull/4/head
hevinci 2022-03-22 20:15:59 +08:00
parent 578cd7ebb5
commit 8373df547b
10 changed files with 352 additions and 113 deletions

View File

@ -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);
}
}
}
}
/// <summary>
@ -160,19 +126,19 @@ namespace YooAsset
Resources.UnloadUnusedAssets();
}
/// <summary>
/// 异步加载场景
/// </summary>
/// <param name="scenePath">场景名称</param>
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
/// <summary>
/// 异步加载资源对象
/// </summary>
/// <param name="assetPath">资源路径</param>
/// <param name="assetType">资源类型</param>
public static AssetOperationHandle LoadAssetAsync(string assetPath, System.Type assetType)
{
AssetProviderBase provider = TryGetAssetProvider(assetPath);
@ -200,9 +164,7 @@ namespace YooAsset
/// <summary>
/// 异步加载所有子资源对象
/// </summary>
/// <param name="assetPath">资源路径</param>
/// <param name="assetType">资源类型</param>、
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;
}

View File

@ -76,5 +76,13 @@ namespace YooAsset
return;
_provider.WaitForAsyncComplete();
}
/// <summary>
/// 释放资源句柄
/// </summary>
public void Release()
{
this.ReleaseInternal();
}
}
}

View File

@ -70,7 +70,7 @@ namespace YooAsset
/// <summary>
/// 释放句柄
/// </summary>
public void Release()
internal void ReleaseInternal()
{
if (IsValid == false)
return;

View File

@ -1,8 +1,114 @@

using UnityEngine;
using UnityEngine.SceneManagement;
namespace YooAsset
{
public class SceneOperationHandle : OperationHandleBase
{
/// <summary>
/// 场景卸载异步操作类
/// </summary>
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;
/// <summary>
/// 场景卸载进度
/// </summary>
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<SceneOperationHandle> _callback;
internal SceneOperationHandle(AssetProviderBase provider) : base(provider)
@ -41,13 +147,13 @@ namespace YooAsset
/// <summary>
/// 场景对象
/// </summary>
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;
}
}
/// <summary>
/// 异步卸载场景
/// </summary>
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();
}
}
}
}

View File

@ -0,0 +1,92 @@

namespace YooAsset
{
public class SubAssetsOperationHandle : OperationHandleBase
{
private System.Action<SubAssetsOperationHandle> _callback;
internal SubAssetsOperationHandle(AssetProviderBase provider) : base(provider)
{
}
internal override void InvokeCallback()
{
if (IsValid)
{
_callback?.Invoke(this);
}
}
/// <summary>
/// 完成委托
/// </summary>
public event System.Action<SubAssetsOperationHandle> 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;
}
}
/// <summary>
/// 子资源对象集合
/// </summary>
public UnityEngine.Object[] AllAssetObjects
{
get
{
if (IsValid == false)
return null;
return _provider.AllAssets;
}
}
/// <summary>
/// 获取子资源对象
/// </summary>
/// <typeparam name="TObject">子资源对象类型</typeparam>
/// <param name="assetName">子资源对象名称</param>
public TObject GetSubAssetObject<TObject>(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;
}
/// <summary>
/// 等待异步执行完毕
/// </summary>
public void WaitForAsyncComplete()
{
if (IsValid == false)
return;
_provider.WaitForAsyncComplete();
}
/// <summary>
/// 释放资源句柄
/// </summary>
public void Release()
{
this.ReleaseInternal();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 76b148be04a698e45a54dd85e64969dd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -43,7 +43,7 @@ namespace YooAsset
/// <summary>
/// 获取的场景对象
/// </summary>
public UnityEngine.SceneManagement.Scene Scene { protected set; get; }
public UnityEngine.SceneManagement.Scene SceneObject { protected set; get; }
/// <summary>
@ -108,6 +108,17 @@ namespace YooAsset
IsDestroyed = true;
}
/// <summary>
/// 是否可以销毁
/// </summary>
public bool CanDestroy()
{
if (IsDone == false)
return false;
return RefCount <= 0;
}
/// <summary>
/// 创建操作句柄
/// </summary>
@ -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--;
}
/// <summary>
/// 是否可以销毁
/// </summary>
public bool CanDestroy()
{
if (IsDone == false)
return false;
return RefCount <= 0;
}
/// <summary>
/// 是否为场景提供者
/// </summary>
@ -164,6 +166,17 @@ namespace YooAsset
return false;
}
/// <summary>
/// 是否为子资源对象提供者
/// </summary>
public bool IsSubAssetsProvider()
{
if (this is BundledSubAssetsProvider || this is DatabaseSubAssetsProvider)
return true;
else
return false;
}
/// <summary>
/// 等待异步执行完毕
/// </summary>

View File

@ -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);
}
}
}
}

View File

@ -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
}
}

View File

@ -289,17 +289,18 @@ namespace YooAsset
AssetSystem.GetDebugReport(report);
}
#region 场景接口
#region 场景加载接口
/// <summary>
/// 异步加载场景
/// </summary>
/// <param name="location">场景对象相对路径</param>
/// <param name="mode">场景加载模式</param>
/// <param name="sceneMode">场景加载模式</param>
/// <param name="activateOnLoad">加载完毕时是否主动激活</param>
public static SceneOperationHandle LoadSceneAsync(string location, LoadSceneMode mode, bool activateOnLoad)
/// <param name="priority">优先级</param>
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
/// </summary>
/// <typeparam name="TObject">资源类型</typeparam>
/// <param name="location">资源对象相对路径</param>
public static AssetOperationHandle LoadSubAssetsSync<TObject>(string location)
public static SubAssetsOperationHandle LoadSubAssetsSync<TObject>(string location)
{
return LoadSubAssetsInternal(location, typeof(TObject), true);
}
@ -340,7 +341,7 @@ namespace YooAsset
/// </summary>
/// <param name="location">资源对象相对路径</param>
/// <param name="type">子对象类型</param>
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
/// </summary>
/// <typeparam name="TObject">资源类型</typeparam>
/// <param name="location">资源对象相对路径</param>
public static AssetOperationHandle LoadSubAssetsAsync<TObject>(string location)
public static SubAssetsOperationHandle LoadSubAssetsAsync<TObject>(string location)
{
return LoadSubAssetsInternal(location, typeof(TObject), false);
}
@ -381,7 +382,7 @@ namespace YooAsset
/// </summary>
/// <param name="location">资源对象相对路径</param>
/// <param name="type">子对象类型</param>
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);