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++; 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> /// <summary>
@ -160,19 +126,19 @@ namespace YooAsset
Resources.UnloadUnusedAssets(); Resources.UnloadUnusedAssets();
} }
/// <summary> /// <summary>
/// 异步加载场景 /// 异步加载场景
/// </summary> /// </summary>
/// <param name="scenePath">场景名称</param> public static SceneOperationHandle LoadSceneAsync(string scenePath, LoadSceneMode sceneMode, bool activateOnLoad, int priority)
public static SceneOperationHandle LoadSceneAsync(string scenePath, LoadSceneMode mode, bool activateOnLoad)
{ {
AssetProviderBase provider = TryGetAssetProvider(scenePath); AssetProviderBase provider = TryGetAssetProvider(scenePath);
if (provider == null) if (provider == null)
{ {
if (SimulationOnEditor) if (SimulationOnEditor)
provider = new DatabaseSceneProvider(scenePath, mode, activateOnLoad); provider = new DatabaseSceneProvider(scenePath, sceneMode, activateOnLoad, priority);
else else
provider = new BundledSceneProvider(scenePath, mode, activateOnLoad); provider = new BundledSceneProvider(scenePath, sceneMode, activateOnLoad, priority);
_providers.Add(provider); _providers.Add(provider);
} }
return provider.CreateHandle() as SceneOperationHandle; return provider.CreateHandle() as SceneOperationHandle;
@ -181,8 +147,6 @@ namespace YooAsset
/// <summary> /// <summary>
/// 异步加载资源对象 /// 异步加载资源对象
/// </summary> /// </summary>
/// <param name="assetPath">资源路径</param>
/// <param name="assetType">资源类型</param>
public static AssetOperationHandle LoadAssetAsync(string assetPath, System.Type assetType) public static AssetOperationHandle LoadAssetAsync(string assetPath, System.Type assetType)
{ {
AssetProviderBase provider = TryGetAssetProvider(assetPath); AssetProviderBase provider = TryGetAssetProvider(assetPath);
@ -200,9 +164,7 @@ namespace YooAsset
/// <summary> /// <summary>
/// 异步加载所有子资源对象 /// 异步加载所有子资源对象
/// </summary> /// </summary>
/// <param name="assetPath">资源路径</param> public static SubAssetsOperationHandle LoadSubAssetsAsync(string assetPath, System.Type assetType)
/// <param name="assetType">资源类型</param>、
public static AssetOperationHandle LoadSubAssetsAsync(string assetPath, System.Type assetType)
{ {
AssetProviderBase provider = TryGetAssetProvider(assetPath); AssetProviderBase provider = TryGetAssetProvider(assetPath);
if (provider == null) if (provider == null)
@ -213,7 +175,7 @@ namespace YooAsset
provider = new BundledSubAssetsProvider(assetPath, assetType); provider = new BundledSubAssetsProvider(assetPath, assetType);
_providers.Add(provider); _providers.Add(provider);
} }
return provider.CreateHandle() as AssetOperationHandle; return provider.CreateHandle() as SubAssetsOperationHandle;
} }

View File

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

View File

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

View File

@ -1,8 +1,114 @@
 using UnityEngine;
using UnityEngine.SceneManagement;
namespace YooAsset namespace YooAsset
{ {
public class SceneOperationHandle : OperationHandleBase 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; private System.Action<SceneOperationHandle> _callback;
internal SceneOperationHandle(AssetProviderBase provider) : base(provider) internal SceneOperationHandle(AssetProviderBase provider) : base(provider)
@ -41,13 +147,13 @@ namespace YooAsset
/// <summary> /// <summary>
/// 场景对象 /// 场景对象
/// </summary> /// </summary>
public UnityEngine.SceneManagement.Scene Scene public Scene SceneObject
{ {
get get
{ {
if (IsValid == false) if (IsValid == false)
return new UnityEngine.SceneManagement.Scene(); return new Scene();
return _provider.Scene; return _provider.SceneObject;
} }
} }
@ -59,15 +165,79 @@ namespace YooAsset
if (IsValid == false) if (IsValid == false)
return false; return false;
if (Scene.IsValid() && Scene.isLoaded) if (SceneObject.IsValid() && SceneObject.isLoaded)
{ {
return UnityEngine.SceneManagement.SceneManager.SetActiveScene(Scene); return SceneManager.SetActiveScene(SceneObject);
} }
else else
{ {
YooLogger.Warning($"Scene is invalid or not loaded : {Scene.name}"); YooLogger.Warning($"Scene is invalid or not loaded : {SceneObject.name}");
return false; 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>
/// 获取的场景对象 /// 获取的场景对象
/// </summary> /// </summary>
public UnityEngine.SceneManagement.Scene Scene { protected set; get; } public UnityEngine.SceneManagement.Scene SceneObject { protected set; get; }
/// <summary> /// <summary>
@ -108,6 +108,17 @@ namespace YooAsset
IsDestroyed = true; IsDestroyed = true;
} }
/// <summary>
/// 是否可以销毁
/// </summary>
public bool CanDestroy()
{
if (IsDone == false)
return false;
return RefCount <= 0;
}
/// <summary> /// <summary>
/// 创建操作句柄 /// 创建操作句柄
/// </summary> /// </summary>
@ -120,6 +131,8 @@ namespace YooAsset
OperationHandleBase handle; OperationHandleBase handle;
if (IsSceneProvider()) if (IsSceneProvider())
handle = new SceneOperationHandle(this); handle = new SceneOperationHandle(this);
else if (IsSubAssetsProvider())
handle = new SubAssetsOperationHandle(this);
else else
handle = new AssetOperationHandle(this); handle = new AssetOperationHandle(this);
@ -142,17 +155,6 @@ namespace YooAsset
RefCount--; RefCount--;
} }
/// <summary>
/// 是否可以销毁
/// </summary>
public bool CanDestroy()
{
if (IsDone == false)
return false;
return RefCount <= 0;
}
/// <summary> /// <summary>
/// 是否为场景提供者 /// 是否为场景提供者
/// </summary> /// </summary>
@ -164,6 +166,17 @@ namespace YooAsset
return false; return false;
} }
/// <summary>
/// 是否为子资源对象提供者
/// </summary>
public bool IsSubAssetsProvider()
{
if (this is BundledSubAssetsProvider || this is DatabaseSubAssetsProvider)
return true;
else
return false;
}
/// <summary> /// <summary>
/// 等待异步执行完毕 /// 等待异步执行完毕
/// </summary> /// </summary>

View File

@ -7,8 +7,9 @@ namespace YooAsset
{ {
internal sealed class BundledSceneProvider : BundledProvider internal sealed class BundledSceneProvider : BundledProvider
{ {
private readonly LoadSceneMode _sceneMode; public readonly LoadSceneMode SceneMode;
private readonly bool _activateOnLoad; private readonly bool _activateOnLoad;
private readonly int _priority;
private AsyncOperation _asyncOp; private AsyncOperation _asyncOp;
public override float Progress 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) : base(scenePath, null)
{ {
_sceneMode = sceneMode; SceneMode = sceneMode;
_activateOnLoad = activateOnLoad; _activateOnLoad = activateOnLoad;
_priority = priority;
} }
public override void Update() public override void Update()
{ {
@ -58,10 +60,11 @@ namespace YooAsset
// 2. 加载场景 // 2. 加载场景
if (Status == EStatus.Loading) if (Status == EStatus.Loading)
{ {
_asyncOp = SceneManager.LoadSceneAsync(AssetName, _sceneMode); _asyncOp = SceneManager.LoadSceneAsync(AssetName, SceneMode);
if (_asyncOp != null) if (_asyncOp != null)
{ {
_asyncOp.allowSceneActivation = true; _asyncOp.allowSceneActivation = true;
_asyncOp.priority = _priority;
Status = EStatus.Checking; Status = EStatus.Checking;
} }
else else
@ -77,25 +80,14 @@ namespace YooAsset
{ {
if (_asyncOp.isDone) if (_asyncOp.isDone)
{ {
Scene = SceneManager.GetSceneByName(AssetName); SceneObject = SceneManager.GetSceneByName(AssetName);
if (_activateOnLoad) if (SceneObject.IsValid() && _activateOnLoad)
SceneManager.SetActiveScene(Scene); SceneManager.SetActiveScene(SceneObject);
Status = Scene.IsValid() ? EStatus.Success : EStatus.Fail; Status = SceneObject.IsValid() ? EStatus.Success : EStatus.Fail;
InvokeCompletion(); 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 internal sealed class DatabaseSceneProvider : AssetProviderBase
{ {
private readonly LoadSceneMode _sceneMode; public readonly LoadSceneMode SceneMode;
private readonly bool _activateOnLoad; private readonly bool _activateOnLoad;
private readonly int _priority;
private AsyncOperation _asyncOp; private AsyncOperation _asyncOp;
public override float Progress 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) : base(scenePath, null)
{ {
_sceneMode = sceneMode; SceneMode = sceneMode;
_activateOnLoad = activateOnLoad; _activateOnLoad = activateOnLoad;
_priority = priority;
} }
public override void Update() public override void Update()
{ {
@ -39,11 +41,12 @@ namespace YooAsset
if (Status == EStatus.Loading) if (Status == EStatus.Loading)
{ {
LoadSceneParameters loadSceneParameters = new LoadSceneParameters(); LoadSceneParameters loadSceneParameters = new LoadSceneParameters();
loadSceneParameters.loadSceneMode = _sceneMode; loadSceneParameters.loadSceneMode = SceneMode;
_asyncOp = UnityEditor.SceneManagement.EditorSceneManager.LoadSceneAsyncInPlayMode(AssetPath, loadSceneParameters); _asyncOp = UnityEditor.SceneManagement.EditorSceneManager.LoadSceneAsyncInPlayMode(AssetPath, loadSceneParameters);
if (_asyncOp != null) if (_asyncOp != null)
{ {
_asyncOp.allowSceneActivation = true; _asyncOp.allowSceneActivation = true;
_asyncOp.priority = _priority;
Status = EStatus.Checking; Status = EStatus.Checking;
} }
else else
@ -59,27 +62,14 @@ namespace YooAsset
{ {
if (_asyncOp.isDone) if (_asyncOp.isDone)
{ {
Scene = SceneManager.GetSceneAt(SceneManager.sceneCount - 1); SceneObject = SceneManager.GetSceneAt(SceneManager.sceneCount - 1);
if (_activateOnLoad) if (SceneObject.IsValid() && _activateOnLoad)
SceneManager.SetActiveScene(Scene); SceneManager.SetActiveScene(SceneObject);
Status = Scene.IsValid() ? EStatus.Success : EStatus.Fail; Status = SceneObject.IsValid() ? EStatus.Success : EStatus.Fail;
InvokeCompletion(); InvokeCompletion();
} }
} }
#endif
}
public override void Destory()
{
#if UNITY_EDITOR
base.Destory();
// 卸载附加场景(异步方式卸载)
if (_sceneMode == LoadSceneMode.Additive)
{
if (Scene.IsValid() && Scene.isLoaded)
SceneManager.UnloadSceneAsync(Scene);
}
#endif #endif
} }
} }

View File

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