using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
namespace YooAsset
{
internal abstract class ProviderBase
{
public enum EStatus
{
None = 0,
CheckBundle,
Loading,
Checking,
Succeed,
Failed,
}
///
/// 资源提供者唯一标识符
///
public string ProviderGUID { private set; get; }
///
/// 所属资源系统
///
public AssetSystemImpl Impl { private set; get; }
///
/// 资源信息
///
public AssetInfo MainAssetInfo { private set; get; }
///
/// 获取的资源对象
///
public UnityEngine.Object AssetObject { protected set; get; }
///
/// 获取的资源对象集合
///
public UnityEngine.Object[] AllAssetObjects { protected set; get; }
///
/// 获取的场景对象
///
public UnityEngine.SceneManagement.Scene SceneObject { protected set; get; }
///
/// 原生文件路径
///
public string RawFilePath { protected set; get; }
///
/// 当前的加载状态
///
public EStatus Status { protected set; get; } = EStatus.None;
///
/// 最近的错误信息
///
public string LastError { protected set; get; } = string.Empty;
///
/// 加载进度
///
public float Progress { protected set; get; } = 0f;
///
/// 引用计数
///
public int RefCount { private set; get; } = 0;
///
/// 是否已经销毁
///
public bool IsDestroyed { private set; get; } = false;
///
/// 是否完毕(成功或失败)
///
public bool IsDone
{
get
{
return Status == EStatus.Succeed || Status == EStatus.Failed;
}
}
protected BundleLoaderBase OwnerBundle { private set; get; }
protected DependAssetBundles DependBundles { private set; get; }
protected bool IsWaitForAsyncComplete { private set; get; } = false;
private readonly List _handles = new List();
public ProviderBase(AssetSystemImpl impl, string providerGUID, AssetInfo assetInfo)
{
Impl = impl;
ProviderGUID = providerGUID;
MainAssetInfo = assetInfo;
// 创建资源包加载器
if (impl != null)
{
OwnerBundle = impl.CreateOwnerAssetBundleLoader(assetInfo);
OwnerBundle.Reference();
OwnerBundle.AddProvider(this);
var dependList = impl.CreateDependAssetBundleLoaders(assetInfo);
DependBundles = new DependAssetBundles(dependList);
DependBundles.Reference();
}
}
///
/// 轮询更新方法
///
public abstract void Update();
///
/// 销毁资源对象
///
public void Destroy()
{
IsDestroyed = true;
// 释放资源包加载器
if (OwnerBundle != null)
{
OwnerBundle.Release();
OwnerBundle = null;
}
if (DependBundles != null)
{
DependBundles.Release();
DependBundles = null;
}
}
///
/// 是否可以销毁
///
public bool CanDestroy()
{
if (IsDone == false)
return false;
return RefCount <= 0;
}
///
/// 是否为场景提供者
///
public bool IsSceneProvider()
{
if (this is BundledSceneProvider || this is DatabaseSceneProvider)
return true;
else
return false;
}
///
/// 创建操作句柄
///
public T CreateHandle() where T : OperationHandleBase
{
// 引用计数增加
RefCount++;
OperationHandleBase handle;
if (typeof(T) == typeof(AssetOperationHandle))
handle = new AssetOperationHandle(this);
else if (typeof(T) == typeof(SceneOperationHandle))
handle = new SceneOperationHandle(this);
else if (typeof(T) == typeof(SubAssetsOperationHandle))
handle = new SubAssetsOperationHandle(this);
else if (typeof(T) == typeof(AllAssetsOperationHandle))
handle = new AllAssetsOperationHandle(this);
else if (typeof(T) == typeof(RawFileOperationHandle))
handle = new RawFileOperationHandle(this);
else
throw new System.NotImplementedException();
_handles.Add(handle);
return handle as T;
}
///
/// 释放操作句柄
///
public void ReleaseHandle(OperationHandleBase handle)
{
if (RefCount <= 0)
YooLogger.Warning("Asset provider reference count is already zero. There may be resource leaks !");
if (_handles.Remove(handle) == false)
throw new System.Exception("Should never get here !");
// 引用计数减少
RefCount--;
}
///
/// 等待异步执行完毕
///
public void WaitForAsyncComplete()
{
IsWaitForAsyncComplete = true;
// 注意:主动轮询更新完成同步加载
Update();
// 验证结果
if (IsDone == false)
{
YooLogger.Warning($"WaitForAsyncComplete failed to loading : {MainAssetInfo.AssetPath}");
}
}
///
/// 处理特殊异常
///
protected void ProcessCacheBundleException()
{
if (OwnerBundle.IsDestroyed)
throw new System.Exception("Should never get here !");
if (OwnerBundle.MainBundleInfo.Bundle.IsRawFile)
{
Status = EStatus.Failed;
LastError = $"Cannot load asset bundle file using {nameof(ResourcePackage.LoadRawFileAsync)} method !";
YooLogger.Error(LastError);
InvokeCompletion();
}
else
{
Status = EStatus.Failed;
LastError = $"The bundle {OwnerBundle.MainBundleInfo.Bundle.BundleName} has been destroyed by unity bugs !";
YooLogger.Error(LastError);
InvokeCompletion();
}
}
///
/// 异步操作任务
///
public Task Task
{
get
{
if (_taskCompletionSource == null)
{
_taskCompletionSource = new TaskCompletionSource