2023-04-03 11:04:31 +08:00

246 lines
8.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
using System;
using System.Collections.Generic;
using System.IO;
namespace BF
{
public class AssetBundleObject : AssetObjectBase
{
public static Dictionary<string, string> fullpathDict = new Dictionary<string, string>();
public AssetBundleConfig AssetBundleConfig { get; private set; }
public AssetBundle Assetbundle { get; private set; }
private AssetBundleCreateRequest request;
private BFEvent<AssetBundleObject> loadComplete;
private BFEvent unloadComplete;
public float Timeout { get; private set; } //异步加载的超时机制,保证不会一直卡在这里
private int recordDependCount;
private string[] dependAB;
private AssetBundleLoader assetBundleLoader;
private bool dependABComplete = false;
public AssetBundleObject(AssetBundleConfig config, AssetBundleLoader loader) : base(config.assetBundlePath, null)
{
AssetBundleConfig = config;
assetBundleLoader = loader;
loadComplete = new BFEvent<AssetBundleObject>();
unloadComplete = new BFEvent();
dependAB = loader.Manifest.GetAllDependencies(config.assetBundlePath);
dependABComplete = dependAB.Length == 0;
recordDependCount = dependAB.Length;
for (int i = 0; i < dependAB.Length; i++)
{
BFLog.LogDebug(BFLog.DEBUG_RESMGR, "green", "[ResMgr] [AssetBundleObject] assetpath : {2} index : {0}, depend : {1}", i, dependAB[i], AssetPath);
assetBundleLoader.LoadDependBundleAsync(dependAB[i], LoadCompleteDepenedAsset);
}
}
public void LoadBundleAsync(Action<AssetBundleObject> callback)
{
++RefCount;
if (EAssetLoadStatus.Complete == LoadStatus || EAssetLoadStatus.Error == LoadStatus)
{
callback(this);
}
else if (EAssetLoadStatus.Unloading == LoadStatus)
{
LoadStatus = EAssetLoadStatus.Complete;
callback(this);
}
else
{
loadComplete += callback;
}
}
public void StartLoadAsync()
{
LoadStatus = EAssetLoadStatus.Loading;
if (!fullpathDict.TryGetValue(AssetPath, out string fullpath))
{
if (AssetBundleConfig.location == 1)
{
fullpath = Path.Combine(Application.persistentDataPath, "update", AssetPath);
}
else
{
fullpath = Path.Combine(Application.streamingAssetsPath, AssetPath);
}
fullpathDict.Add(AssetPath, fullpath);
}
request = AssetBundle.LoadFromFileAsync(fullpath);
Timeout = ResourceManager.TIME_OUT_LOAD + Time.time;
BFLog.LogDebug(BFLog.DEBUG_RESMGR, "green", "StartLoadAsync assetpath : {0}. timeout : {1}", fullpath, Timeout);
}
public void LoadSync(bool ignoreRefCount = false)
{
if (!ignoreRefCount)
{
++RefCount;
}
if(EAssetLoadStatus.Complete == LoadStatus)
{
return;
}
if (EAssetLoadStatus.Loading != LoadStatus)
{
for (int i = 0; i < dependAB.Length; i++)
{
assetBundleLoader.LoadDependBundleSync(dependAB[i]);
}
if (!fullpathDict.TryGetValue(AssetPath, out string fullpath))
{
if (AssetBundleConfig.location == 1)
{
fullpath = Path.Combine(Application.persistentDataPath, "update", AssetPath);
}
else
{
fullpath = Path.Combine(Application.streamingAssetsPath, AssetPath);
}
fullpathDict.Add(AssetPath, fullpath);
}
var ab = AssetBundle.LoadFromFile(fullpath);
Complete(ab);
}
else
{
// 异步过程中转同步
for (int i = 0; i < dependAB.Length; i++)
{
assetBundleLoader.LoadDependBundleSync(dependAB[i]);
}
var ab = request.assetBundle;
Complete(ab);
}
}
private void LoadCompleteDepenedAsset(AssetBundleObject assetBundleObject)
{
recordDependCount--;
if (recordDependCount == 0)
{
dependABComplete = true;
}
BFLog.LogDebug(BFLog.DEBUG_RESMGR, "green", "[AssetBundleObject] [LoadCompleteDepenedAsset] : {0}, record dependent count : {1}", assetBundleObject.AssetPath, recordDependCount);
}
/// <summary>
/// 加载完成返回true, 否则返回false. 超时机制确保不会无法结束
/// </summary>
/// <returns></returns>
public override bool Tick()
{
try
{
if (EAssetLoadStatus.Loading == LoadStatus)
{
if (request != null && request.isDone && dependABComplete)
{
Complete(request.assetBundle);
return true;
}
else
{
if (Timeout < Time.time) //超时机制
{
BFLog.LogError("[ResMgr] bundlepath : {0}, timeout ! assetbunle is null = {1}", AssetPath, (null == Assetbundle));
Timeout += ResourceManager.TIME_OUT_LOAD;
return false;
}
}
}
else if (EAssetLoadStatus.Complete == LoadStatus)
{
return true;
}
return false;
}
catch (Exception ex) //需要测试!!!! 尝试捕获异常,保证单个资源加载出错不卡住游戏。比如异步过程中被同步调用等。
{
BFLog.LogError("[ResMgr] loading exception! assetpath : {0}, exception : {1}", AssetPath, ex.ToString());
return true;
}
}
public void Complete(AssetBundle ab)
{
Assetbundle = ab;
LoadStatus = ab == null ? EAssetLoadStatus.Error : EAssetLoadStatus.Complete;
request = null;
loadComplete.Invoke(this);
loadComplete.Clear();
}
public void AddUnloadCallback(Action unloadCallback)
{
unloadComplete += unloadCallback;
}
public override bool Unload(bool immediately)
{
BFLog.LogDebug(BFLog.DEBUG_RESMGR, "green", "[ResMgr] assetBundleobject base unload assetpath : {0}, refcount : {1}", AssetPath, RefCount);
if (RefCount == 0)
return false;
--RefCount;
if (RefCount == 0)
{
loadComplete.Clear();
LoadStatus = EAssetLoadStatus.Unloading;
BFLog.LogDebug(BFLog.DEBUG_RESMGR, "green", "[ResMgr] assetobject unloaded immediately");
UnloadCountdown(true); // assetbundle目前都是立即卸载
return false;
}
return false;
}
protected override bool OnUnloadComplete()
{
BFLog.LogDebug(BFLog.DEBUG_RESMGR, "green", "[ResMgr] AssetBundleObject OnUnloadComplete start LoadStatus : {0}", LoadStatus);
if (EAssetLoadStatus.Complete == LoadStatus)
{
return false;
}
if (!ReferenceEquals(null, request))
{
var assetbundle = request.assetBundle;
assetbundle.Unload(true);
request = null;
}
if (!ReferenceEquals(null, Assetbundle))
{
Assetbundle.Unload(true);
Assetbundle = null;
}
LoadStatus = EAssetLoadStatus.Unloaded;
assetBundleLoader.RemoveCache(this);
unloadComplete.Invoke();
unloadComplete.Clear();
for (int i = 0; i < dependAB.Length; i++)
{
assetBundleLoader.UnLoadBundle(dependAB[i], true);
}
BFLog.LogDebug(BFLog.DEBUG_RESMGR, "green", "[ResMgr] OnUnloadComplete end ");
return true;
}
}
}