update asset system

编辑器模拟模式增加虚拟资源包
pull/86/head
hevinci 2023-03-24 18:33:36 +08:00
parent c60cc1e84f
commit de43495af5
14 changed files with 286 additions and 132 deletions

View File

@ -69,7 +69,6 @@ namespace YooAsset
// 更新资源提供者 // 更新资源提供者
// 注意:循环更新的时候,可能会扩展列表 // 注意:循环更新的时候,可能会扩展列表
// 注意:不能限制场景对象的加载
_isUnloadSafe = false; _isUnloadSafe = false;
for (int i = 0; i < _providerList.Count; i++) for (int i = 0; i < _providerList.Count; i++)
{ {
@ -123,27 +122,13 @@ namespace YooAsset
} }
} }
private void UnloadUnusedAssetsInternal() private void UnloadUnusedAssetsInternal()
{
if (_simulationOnEditor)
{
for (int i = _providerList.Count - 1; i >= 0; i--)
{
var provider = _providerList[i];
if (provider.CanDestroy())
{
provider.Destroy();
_providerList.RemoveAt(i);
_providerDic.Remove(provider.ProviderGUID);
}
}
}
else
{ {
for (int i = _loaderList.Count - 1; i >= 0; i--) for (int i = _loaderList.Count - 1; i >= 0; i--)
{ {
BundleLoaderBase loader = _loaderList[i]; BundleLoaderBase loader = _loaderList[i];
loader.TryDestroyAllProviders(); loader.TryDestroyAllProviders();
} }
for (int i = _loaderList.Count - 1; i >= 0; i--) for (int i = _loaderList.Count - 1; i >= 0; i--)
{ {
BundleLoaderBase loader = _loaderList[i]; BundleLoaderBase loader = _loaderList[i];
@ -156,7 +141,6 @@ namespace YooAsset
} }
} }
} }
}
/// <summary> /// <summary>
/// 强制回收所有资源 /// 强制回收所有资源
@ -392,6 +376,12 @@ namespace YooAsset
return loader; return loader;
// 新增下载需求 // 新增下载需求
if (_simulationOnEditor)
{
loader = new VirtualBundleFileLoader(this, bundleInfo);
}
else
{
#if UNITY_WEBGL #if UNITY_WEBGL
if (bundleInfo.Bundle.IsRawFile) if (bundleInfo.Bundle.IsRawFile)
loader = new RawBundleWebLoader(this, bundleInfo); loader = new RawBundleWebLoader(this, bundleInfo);
@ -403,6 +393,7 @@ namespace YooAsset
else else
loader = new AssetBundleFileLoader(this, bundleInfo); loader = new AssetBundleFileLoader(this, bundleInfo);
#endif #endif
}
_loaderList.Add(loader); _loaderList.Add(loader);
_loaderDic.Add(bundleName, loader); _loaderDic.Add(bundleName, loader);
@ -437,13 +428,8 @@ namespace YooAsset
providerInfo.RefCount = provider.RefCount; providerInfo.RefCount = provider.RefCount;
providerInfo.Status = provider.Status.ToString(); providerInfo.Status = provider.Status.ToString();
providerInfo.DependBundleInfos = new List<DebugBundleInfo>(); providerInfo.DependBundleInfos = new List<DebugBundleInfo>();
provider.GetBundleDebugInfos(providerInfo.DependBundleInfos);
result.Add(providerInfo); result.Add(providerInfo);
if (provider is BundledProvider)
{
BundledProvider temp = provider as BundledProvider;
temp.GetBundleDebugInfos(providerInfo.DependBundleInfos);
}
} }
return result; return result;
} }

View File

@ -0,0 +1,82 @@

namespace YooAsset
{
internal class VirtualBundleFileLoader : BundleLoaderBase
{
private enum ESteps
{
None,
CheckFile,
Done,
}
private ESteps _steps = ESteps.None;
public VirtualBundleFileLoader(AssetSystemImpl impl, BundleInfo bundleInfo) : base(impl, bundleInfo)
{
}
/// <summary>
/// 轮询更新
/// </summary>
public override void Update()
{
if (_steps == ESteps.Done)
return;
if (_steps == ESteps.None)
{
if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromEditor)
{
_steps = ESteps.CheckFile;
}
else
{
throw new System.NotImplementedException(MainBundleInfo.LoadMode.ToString());
}
}
// 1. 检测结果
if (_steps == ESteps.CheckFile)
{
// 设置下载进度
DownloadProgress = 1f;
DownloadedBytes = (ulong)MainBundleInfo.Bundle.FileSize;
_steps = ESteps.Done;
Status = EStatus.Succeed;
}
}
/// <summary>
/// 主线程等待异步操作完毕
/// </summary>
public override void WaitForAsyncComplete()
{
int frame = 1000;
while (true)
{
// 保险机制
// 注意:如果需要从远端下载资源,可能会触发保险机制!
frame--;
if (frame == 0)
{
if (IsDone() == false)
{
Status = EStatus.Failed;
LastError = $"WaitForAsyncComplete failed ! Try load bundle : {MainBundleInfo.Bundle.BundleName} from remote with sync load method !";
YooLogger.Error(LastError);
}
break;
}
// 驱动流程
Update();
// 完成后退出
if (IsDone())
break;
}
}
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 4eacb00a7e3873740b599112dfcf0123 guid: 7b9023a940b496549894d9d8872219fb
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@ -4,7 +4,7 @@ using UnityEngine;
namespace YooAsset namespace YooAsset
{ {
internal sealed class BundledAssetProvider : BundledProvider internal sealed class BundledAssetProvider : ProviderBase
{ {
private AssetBundleRequest _cacheRequest; private AssetBundleRequest _cacheRequest;

View File

@ -1,69 +0,0 @@
using System.Collections;
using System.Collections.Generic;
namespace YooAsset
{
internal abstract class BundledProvider : ProviderBase
{
protected BundleLoaderBase OwnerBundle { private set; get; }
protected DependAssetBundleGroup DependBundleGroup { private set; get; }
public BundledProvider(AssetSystemImpl impl, string providerGUID, AssetInfo assetInfo) : base(impl, providerGUID, assetInfo)
{
OwnerBundle = impl.CreateOwnerAssetBundleLoader(assetInfo);
OwnerBundle.Reference();
OwnerBundle.AddProvider(this);
var dependBundles = impl.CreateDependAssetBundleLoaders(assetInfo);
DependBundleGroup = new DependAssetBundleGroup(dependBundles);
DependBundleGroup.Reference();
}
public override void Destroy()
{
base.Destroy();
// 释放资源包
if (OwnerBundle != null)
{
OwnerBundle.Release();
OwnerBundle = null;
}
if (DependBundleGroup != null)
{
DependBundleGroup.Release();
DependBundleGroup = null;
}
}
/// <summary>
/// 获取下载报告
/// </summary>
public override DownloadReport GetDownloadReport()
{
DownloadReport result = new DownloadReport();
result.TotalSize = (ulong)OwnerBundle.MainBundleInfo.Bundle.FileSize;
result.DownloadedBytes = OwnerBundle.DownloadedBytes;
foreach (var dependBundle in DependBundleGroup.DependBundles)
{
result.TotalSize += (ulong)dependBundle.MainBundleInfo.Bundle.FileSize;
result.DownloadedBytes += dependBundle.DownloadedBytes;
}
result.Progress = (float)result.DownloadedBytes / result.TotalSize;
return result;
}
/// <summary>
/// 获取资源包的调试信息列表
/// </summary>
internal void GetBundleDebugInfos(List<DebugBundleInfo> output)
{
var bundleInfo = new DebugBundleInfo();
bundleInfo.BundleName = OwnerBundle.MainBundleInfo.Bundle.BundleName;
bundleInfo.RefCount = OwnerBundle.RefCount;
bundleInfo.Status = OwnerBundle.Status.ToString();
output.Add(bundleInfo);
DependBundleGroup.GetBundleDebugInfos(output);
}
}
}

View File

@ -1,7 +1,7 @@
 
namespace YooAsset namespace YooAsset
{ {
internal class BundledRawFileProvider : BundledProvider internal class BundledRawFileProvider : ProviderBase
{ {
public BundledRawFileProvider(AssetSystemImpl impl, string providerGUID, AssetInfo assetInfo) : base(impl, providerGUID, assetInfo) public BundledRawFileProvider(AssetSystemImpl impl, string providerGUID, AssetInfo assetInfo) : base(impl, providerGUID, assetInfo)
{ {
@ -18,6 +18,7 @@ namespace YooAsset
Status = EStatus.CheckBundle; Status = EStatus.CheckBundle;
} }
// 1. 检测资源包
if (Status == EStatus.CheckBundle) if (Status == EStatus.CheckBundle)
{ {
if (IsWaitForAsyncComplete) if (IsWaitForAsyncComplete)
@ -39,6 +40,7 @@ namespace YooAsset
Status = EStatus.Checking; Status = EStatus.Checking;
} }
// 2. 检测加载结果
if (Status == EStatus.Checking) if (Status == EStatus.Checking)
{ {
RawFilePath = OwnerBundle.FileLoadPath; RawFilePath = OwnerBundle.FileLoadPath;

View File

@ -6,7 +6,7 @@ using UnityEngine.SceneManagement;
namespace YooAsset namespace YooAsset
{ {
internal sealed class BundledSceneProvider : BundledProvider internal sealed class BundledSceneProvider : ProviderBase
{ {
public readonly LoadSceneMode SceneMode; public readonly LoadSceneMode SceneMode;
private readonly string _sceneName; private readonly string _sceneName;

View File

@ -4,7 +4,7 @@ using UnityEngine;
namespace YooAsset namespace YooAsset
{ {
internal sealed class BundledSubAssetsProvider : BundledProvider internal sealed class BundledSubAssetsProvider : ProviderBase
{ {
private AssetBundleRequest _cacheRequest; private AssetBundleRequest _cacheRequest;

View File

@ -28,14 +28,36 @@ namespace YooAsset
return; return;
} }
Status = EStatus.Loading; Status = EStatus.CheckBundle;
// 注意:模拟异步加载效果提前返回 // 注意:模拟异步加载效果提前返回
if (IsWaitForAsyncComplete == false) if (IsWaitForAsyncComplete == false)
return; return;
} }
// 1. 加载资源对象 // 1. 检测资源包
if (Status == EStatus.CheckBundle)
{
if (IsWaitForAsyncComplete)
{
OwnerBundle.WaitForAsyncComplete();
}
if (OwnerBundle.IsDone() == false)
return;
if (OwnerBundle.Status != BundleLoaderBase.EStatus.Succeed)
{
Status = EStatus.Failed;
LastError = OwnerBundle.LastError;
InvokeCompletion();
return;
}
Status = EStatus.Loading;
}
// 2. 加载资源对象
if (Status == EStatus.Loading) if (Status == EStatus.Loading)
{ {
if (MainAssetInfo.AssetType == null) if (MainAssetInfo.AssetType == null)
@ -45,7 +67,7 @@ namespace YooAsset
Status = EStatus.Checking; Status = EStatus.Checking;
} }
// 2. 检测加载结果 // 3. 检测加载结果
if (Status == EStatus.Checking) if (Status == EStatus.Checking)
{ {
Status = AssetObject == null ? EStatus.Failed : EStatus.Succeed; Status = AssetObject == null ? EStatus.Failed : EStatus.Succeed;

View File

@ -25,14 +25,37 @@ namespace YooAsset
return; return;
} }
Status = EStatus.Checking; Status = EStatus.CheckBundle;
// 注意:模拟异步加载效果提前返回 // 注意:模拟异步加载效果提前返回
if (IsWaitForAsyncComplete == false) if (IsWaitForAsyncComplete == false)
return; return;
} }
if(Status == EStatus.Checking) // 1. 检测资源包
if (Status == EStatus.CheckBundle)
{
if (IsWaitForAsyncComplete)
{
OwnerBundle.WaitForAsyncComplete();
}
if (OwnerBundle.IsDone() == false)
return;
if (OwnerBundle.Status != BundleLoaderBase.EStatus.Succeed)
{
Status = EStatus.Failed;
LastError = OwnerBundle.LastError;
InvokeCompletion();
return;
}
Status = EStatus.Checking;
}
// 2. 检测加载结果
if (Status == EStatus.Checking)
{ {
RawFilePath = MainAssetInfo.AssetPath; RawFilePath = MainAssetInfo.AssetPath;
Status = EStatus.Succeed; Status = EStatus.Succeed;

View File

@ -24,10 +24,32 @@ namespace YooAsset
if (Status == EStatus.None) if (Status == EStatus.None)
{ {
Status = EStatus.CheckBundle;
}
// 1. 检测资源包
if (Status == EStatus.CheckBundle)
{
if (IsWaitForAsyncComplete)
{
OwnerBundle.WaitForAsyncComplete();
}
if (OwnerBundle.IsDone() == false)
return;
if (OwnerBundle.Status != BundleLoaderBase.EStatus.Succeed)
{
Status = EStatus.Failed;
LastError = OwnerBundle.LastError;
InvokeCompletion();
return;
}
Status = EStatus.Loading; Status = EStatus.Loading;
} }
// 1. 加载资源对象 // 2. 加载资源对象
if (Status == EStatus.Loading) if (Status == EStatus.Loading)
{ {
LoadSceneParameters loadSceneParameters = new LoadSceneParameters(); LoadSceneParameters loadSceneParameters = new LoadSceneParameters();
@ -49,7 +71,7 @@ namespace YooAsset
} }
} }
// 2. 检测加载结果 // 3. 检测加载结果
if (Status == EStatus.Checking) if (Status == EStatus.Checking)
{ {
Progress = _asyncOp.progress; Progress = _asyncOp.progress;

View File

@ -28,14 +28,36 @@ namespace YooAsset
return; return;
} }
Status = EStatus.Loading; Status = EStatus.CheckBundle;
// 注意:模拟异步加载效果提前返回 // 注意:模拟异步加载效果提前返回
if (IsWaitForAsyncComplete == false) if (IsWaitForAsyncComplete == false)
return; return;
} }
// 1. 加载资源对象 // 1. 检测资源包
if (Status == EStatus.CheckBundle)
{
if (IsWaitForAsyncComplete)
{
OwnerBundle.WaitForAsyncComplete();
}
if (OwnerBundle.IsDone() == false)
return;
if (OwnerBundle.Status != BundleLoaderBase.EStatus.Succeed)
{
Status = EStatus.Failed;
LastError = OwnerBundle.LastError;
InvokeCompletion();
return;
}
Status = EStatus.Loading;
}
// 2. 加载资源对象
if (Status == EStatus.Loading) if (Status == EStatus.Loading)
{ {
if (MainAssetInfo.AssetType == null) if (MainAssetInfo.AssetType == null)
@ -56,7 +78,7 @@ namespace YooAsset
Status = EStatus.Checking; Status = EStatus.Checking;
} }
// 2. 检测加载结果 // 3. 检测加载结果
if (Status == EStatus.Checking) if (Status == EStatus.Checking)
{ {
Status = AllAssetObjects == null ? EStatus.Failed : EStatus.Succeed; Status = AllAssetObjects == null ? EStatus.Failed : EStatus.Succeed;

View File

@ -90,6 +90,8 @@ namespace YooAsset
} }
protected BundleLoaderBase OwnerBundle { private set; get; }
protected DependAssetBundleGroup DependBundleGroup { private set; get; }
protected bool IsWaitForAsyncComplete { private set; get; } = false; protected bool IsWaitForAsyncComplete { private set; get; } = false;
private readonly List<OperationHandleBase> _handles = new List<OperationHandleBase>(); private readonly List<OperationHandleBase> _handles = new List<OperationHandleBase>();
@ -99,6 +101,15 @@ namespace YooAsset
Impl = impl; Impl = impl;
ProviderGUID = providerGUID; ProviderGUID = providerGUID;
MainAssetInfo = assetInfo; MainAssetInfo = assetInfo;
// 创建资源包加载器
OwnerBundle = impl.CreateOwnerAssetBundleLoader(assetInfo);
OwnerBundle.Reference();
OwnerBundle.AddProvider(this);
var dependBundles = impl.CreateDependAssetBundleLoaders(assetInfo);
DependBundleGroup = new DependAssetBundleGroup(dependBundles);
DependBundleGroup.Reference();
} }
/// <summary> /// <summary>
@ -112,14 +123,18 @@ namespace YooAsset
public virtual void Destroy() public virtual void Destroy()
{ {
IsDestroyed = true; IsDestroyed = true;
}
/// <summary> // 释放资源包加载器
/// 获取下载进度 if (OwnerBundle != null)
/// </summary>
public virtual DownloadReport GetDownloadReport()
{ {
return DownloadReport.CreateDefaultReport(); OwnerBundle.Release();
OwnerBundle = null;
}
if (DependBundleGroup != null)
{
DependBundleGroup.Release();
DependBundleGroup = null;
}
} }
/// <summary> /// <summary>
@ -292,6 +307,37 @@ namespace YooAsset
_watch = null; _watch = null;
} }
} }
/// <summary>
/// 获取下载报告
/// </summary>
internal DownloadReport GetDownloadReport()
{
DownloadReport result = new DownloadReport();
result.TotalSize = (ulong)OwnerBundle.MainBundleInfo.Bundle.FileSize;
result.DownloadedBytes = OwnerBundle.DownloadedBytes;
foreach (var dependBundle in DependBundleGroup.DependBundles)
{
result.TotalSize += (ulong)dependBundle.MainBundleInfo.Bundle.FileSize;
result.DownloadedBytes += dependBundle.DownloadedBytes;
}
result.Progress = (float)result.DownloadedBytes / result.TotalSize;
return result;
}
/// <summary>
/// 获取资源包的调试信息列表
/// </summary>
internal void GetBundleDebugInfos(List<DebugBundleInfo> output)
{
var bundleInfo = new DebugBundleInfo();
bundleInfo.BundleName = OwnerBundle.MainBundleInfo.Bundle.BundleName;
bundleInfo.RefCount = OwnerBundle.RefCount;
bundleInfo.Status = OwnerBundle.Status.ToString();
output.Add(bundleInfo);
DependBundleGroup.GetBundleDebugInfos(output);
}
#endregion #endregion
} }
} }

View File

@ -80,6 +80,14 @@ namespace YooAsset
#endregion #endregion
#region IBundleServices接口 #region IBundleServices接口
private BundleInfo CreateBundleInfo(PackageBundle packageBundle, AssetInfo assetInfo)
{
if (packageBundle == null)
throw new Exception("Should never get here !");
BundleInfo bundleInfo = new BundleInfo(packageBundle, BundleInfo.ELoadMode.LoadFromEditor, assetInfo.AssetPath);
return bundleInfo;
}
BundleInfo IBundleServices.GetBundleInfo(AssetInfo assetInfo) BundleInfo IBundleServices.GetBundleInfo(AssetInfo assetInfo)
{ {
if (assetInfo.IsInvalid) if (assetInfo.IsInvalid)
@ -87,16 +95,26 @@ namespace YooAsset
// 注意:如果清单里未找到资源包会抛出异常! // 注意:如果清单里未找到资源包会抛出异常!
var packageBundle = _activeManifest.GetMainPackageBundle(assetInfo.AssetPath); var packageBundle = _activeManifest.GetMainPackageBundle(assetInfo.AssetPath);
BundleInfo bundleInfo = new BundleInfo(packageBundle, BundleInfo.ELoadMode.LoadFromEditor, assetInfo.AssetPath); return CreateBundleInfo(packageBundle, assetInfo);
return bundleInfo;
} }
BundleInfo[] IBundleServices.GetAllDependBundleInfos(AssetInfo assetInfo) BundleInfo[] IBundleServices.GetAllDependBundleInfos(AssetInfo assetInfo)
{ {
throw new NotImplementedException(); if (assetInfo.IsInvalid)
throw new Exception("Should never get here !");
// 注意:如果清单里未找到资源包会抛出异常!
var depends = _activeManifest.GetAllDependencies(assetInfo.AssetPath);
List<BundleInfo> result = new List<BundleInfo>(depends.Length);
foreach (var packageBundle in depends)
{
BundleInfo bundleInfo = CreateBundleInfo(packageBundle, assetInfo);
result.Add(bundleInfo);
}
return result.ToArray();
} }
string IBundleServices.GetBundleName(int bundleID) string IBundleServices.GetBundleName(int bundleID)
{ {
throw new NotImplementedException(); return _activeManifest.GetBundleName(bundleID);
} }
bool IBundleServices.IsServicesValid() bool IBundleServices.IsServicesValid()
{ {