853 lines
30 KiB
C#
853 lines
30 KiB
C#
namespace ZooMatch
|
|
{
|
|
using System;
|
|
using System.IO;
|
|
using UnityEngine;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using UnityEngine.Events;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using Object = UnityEngine.Object;
|
|
using System.Security.Cryptography;
|
|
|
|
public class ZooMatchKit : Singleton<ZooMatchKit>, ILoadAsset
|
|
{
|
|
private const bool IsMD5Encrypt = false;
|
|
|
|
|
|
private string _assetBundleRootPath = ZooMatchFileKit.GetFilePath();
|
|
|
|
|
|
private static readonly Dictionary<string, ZooMatchInfo> _cacheAssetBundleInfoDict =
|
|
new Dictionary<string, ZooMatchInfo>();
|
|
|
|
|
|
private static readonly Dictionary<string, string[]> _cacheDependencyDict = new Dictionary<string, string[]>();
|
|
|
|
private static readonly List<ZooMatchInfo> _waitUnloadList = new List<ZooMatchInfo>();
|
|
|
|
private static AssetBundleManifest _manifest;
|
|
|
|
private static readonly Dictionary<string, string> decryptAssetBundleDict = new Dictionary<string, string>();
|
|
|
|
|
|
private const int UnloadWaitTime = 30;
|
|
|
|
#region 加载AssetBundle的基础方法
|
|
|
|
public IEnumerator LoadABFromFileAsync(string assetBundlePath, string bundlePassword,
|
|
UnityAction<AssetBundle> onCompleted)
|
|
{
|
|
yield return LoadDecryptAssetBundle(assetBundlePath, bundlePassword, onCompleted);
|
|
}
|
|
|
|
private IEnumerator LoadDecryptAssetBundle(string assetBundlePath, string bundlePassword,
|
|
UnityAction<AssetBundle> onCompleted)
|
|
{
|
|
string decryptPath;
|
|
if (decryptAssetBundleDict.TryGetValue(assetBundlePath, out var outPath) && File.Exists(outPath))
|
|
{
|
|
decryptPath = outPath;
|
|
}
|
|
else
|
|
{
|
|
var cachePath1 = Path.Combine(UnityEngine.Application.persistentDataPath, "Jarvis");
|
|
if (!Directory.Exists(cachePath1))
|
|
{
|
|
Directory.CreateDirectory(cachePath1);
|
|
}
|
|
|
|
var cachePath = Path.Combine(cachePath1, $"decryptedBundle{Guid.NewGuid():N}");
|
|
|
|
|
|
using (Stream stream1 = File.OpenWrite(cachePath))
|
|
{
|
|
var decryptedData = AESForFileKit.DecryptToBytes(assetBundlePath, bundlePassword, out var dataSize);
|
|
yield return stream1.WriteAsync(decryptedData, 0, dataSize);
|
|
}
|
|
|
|
decryptPath = cachePath;
|
|
decryptAssetBundleDict.TryAdd(assetBundlePath, decryptPath);
|
|
}
|
|
|
|
var request = AssetBundle.LoadFromFileAsync(decryptPath);
|
|
yield return request;
|
|
onCompleted?.Invoke(request.assetBundle);
|
|
}
|
|
|
|
private AssetBundle LoadDecryptAssetBundleSync(string assetBundlePath, string bundlePassword)
|
|
{
|
|
string decryptPath;
|
|
if (decryptAssetBundleDict.TryGetValue(assetBundlePath, out var outPath) && File.Exists(outPath))
|
|
{
|
|
decryptPath = outPath;
|
|
}
|
|
else
|
|
{
|
|
var decryptedData = AESForFileKit.DecryptToBytes(assetBundlePath, bundlePassword, out var dataSize);
|
|
var cachePath1 = Path.Combine(UnityEngine.Application.persistentDataPath, "Jarvis");
|
|
if (!Directory.Exists(cachePath1))
|
|
{
|
|
Directory.CreateDirectory(cachePath1);
|
|
}
|
|
|
|
var cachePath = Path.Combine(cachePath1, $"decryptedBundle{Guid.NewGuid():N}");
|
|
while (File.Exists(cachePath))
|
|
{
|
|
File.Delete(cachePath);
|
|
cachePath = Path.Combine(cachePath1, $"decryptedBundle{Guid.NewGuid():N}");
|
|
}
|
|
|
|
using (Stream stream = File.OpenWrite(cachePath))
|
|
{
|
|
stream.Write(decryptedData, 0, dataSize);
|
|
stream.Close();
|
|
}
|
|
|
|
decryptPath = cachePath;
|
|
decryptAssetBundleDict.TryAdd(assetBundlePath, decryptPath);
|
|
}
|
|
|
|
var assetBundle = AssetBundle.LoadFromFile(decryptPath);
|
|
return assetBundle;
|
|
}
|
|
|
|
private IEnumerator LoadAssetFromAssetBundle<T>(AssetBundle assetBundle, string assetName,
|
|
UnityAction<T> onLoadCompleted) where T : Object
|
|
{
|
|
T resultAsset = null;
|
|
|
|
if (typeof(T) == typeof(Sprite))
|
|
{
|
|
var texture2D = assetBundle.LoadAsset<Texture2D>(assetName);
|
|
if (texture2D != null)
|
|
{
|
|
var sprite = Sprite.Create(texture2D,
|
|
new Rect(0, 0, texture2D.width, texture2D.height), new Vector2(0.5f, 0.5f));
|
|
|
|
resultAsset = sprite as T;
|
|
}
|
|
else
|
|
{
|
|
string[] assetNameArray = assetName.Split('.');
|
|
if (assetNameArray.Length > 1)
|
|
{
|
|
var resultAsset1 = assetBundle.LoadAssetWithSubAssets<T>(assetNameArray[0]);
|
|
resultAsset = Array.Find(resultAsset1, item => item.name == assetNameArray[1]);
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var assetLoadRequest = assetBundle.LoadAssetAsync<T>(assetName);
|
|
yield return assetLoadRequest;
|
|
var gameObject = assetLoadRequest.asset;
|
|
if (gameObject == null)
|
|
{
|
|
var subAssetLoadRequest = assetBundle.LoadAssetWithSubAssetsAsync<T>(assetName);
|
|
yield return subAssetLoadRequest;
|
|
resultAsset = subAssetLoadRequest.asset as T;
|
|
}
|
|
else
|
|
{
|
|
resultAsset = gameObject as T;
|
|
}
|
|
}
|
|
|
|
onLoadCompleted?.Invoke(resultAsset);
|
|
}
|
|
|
|
private void LoadAssetInternal(string assetBundleName, UnityAction<AssetBundle> onCompleted)
|
|
{
|
|
var assetBundlePath = GenerateAssetBundlePath(assetBundleName);
|
|
|
|
GetAssetBundle(assetBundlePath, assetBundleName, onCompleted);
|
|
}
|
|
|
|
public AssetBundle GetAssetBundle(string assetBundlePath, string assetBundleName)
|
|
{
|
|
assetBundleName = assetBundleName.ToLower();
|
|
CrazyAsyKit.StopAction(assetBundleName + "Unload");
|
|
UnWaitUnload(assetBundleName);
|
|
if (IsCacheAssetBundle(assetBundleName))
|
|
{
|
|
CacheDependency(assetBundleName, new[] { assetBundleName });
|
|
|
|
var LoveLegendInfo = GetCacheAssetBundle(assetBundleName);
|
|
return LoveLegendInfo?.assetBundle;
|
|
}
|
|
else
|
|
{
|
|
var LoveLegendInfo = new ZooMatchInfo(assetBundleName, null);
|
|
CacheAssetBundle(assetBundleName, LoveLegendInfo);
|
|
var isFileLoadType = File.Exists(assetBundlePath);
|
|
if (isFileLoadType)
|
|
{
|
|
GetAssetBundleDependency(assetBundleName);
|
|
var assetBundle =
|
|
LoadDecryptAssetBundleSync(assetBundlePath, ZooMatchConstant.admsie);
|
|
LoveLegendInfo.assetBundle = assetBundle;
|
|
return assetBundle;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public void GetAssetBundle(string assetBundlePath, string assetBundleName, UnityAction<AssetBundle> onCompleted)
|
|
{
|
|
assetBundleName = assetBundleName.ToLower();
|
|
CrazyAsyKit.StopAction(assetBundleName + "Unload");
|
|
UnWaitUnload(assetBundleName);
|
|
if (IsCacheAssetBundle(assetBundleName))
|
|
{
|
|
CacheDependency(assetBundleName, new[] { assetBundleName });
|
|
|
|
var LoveLegendInfo = GetCacheAssetBundle(assetBundleName);
|
|
LoveLegendInfo?.callRes(assetBundleName, onCompleted);
|
|
}
|
|
else
|
|
{
|
|
var LoveLegendInfo = new ZooMatchInfo(assetBundleName, onCompleted);
|
|
CacheAssetBundle(assetBundleName, LoveLegendInfo);
|
|
var isFileLoadType = File.Exists(assetBundlePath);
|
|
CrazyAsyKit.StartCoroutine(GetAssetBundleDependency(assetBundleName, delegate
|
|
{
|
|
if (isFileLoadType)
|
|
{
|
|
CrazyAsyKit.StartCoroutine(LoadABFromFileAsync(assetBundlePath,
|
|
ZooMatchConstant.admsie, bundle =>
|
|
{
|
|
if (bundle == null)
|
|
{
|
|
Debug.LogError("加载AssetBundle 失败:" + assetBundleName);
|
|
UnCacheAssetBundle(assetBundleName);
|
|
}
|
|
else
|
|
{
|
|
ZooMatchInfo abInfo = GetCacheAssetBundle(assetBundleName);
|
|
#if UNITY_EDITOR
|
|
FileInfo file = new FileInfo(assetBundlePath);
|
|
|
|
abInfo.SetAssetBundleSize(file.Length);
|
|
#endif
|
|
abInfo.onLoaded(assetBundleName, bundle);
|
|
}
|
|
}));
|
|
}
|
|
else
|
|
{
|
|
CrazyAsyKit.StartCoroutine(LoadABFromFileAsync(assetBundlePath,
|
|
ZooMatchConstant.admsie, delegate (AssetBundle bundle)
|
|
{
|
|
if (bundle == null)
|
|
{
|
|
Debug.LogError("加载AssetBundle 失败:" + assetBundleName);
|
|
UnCacheAssetBundle(assetBundleName);
|
|
}
|
|
else
|
|
{
|
|
var abInfoV = GetCacheAssetBundle(assetBundleName);
|
|
var file = new FileInfo(assetBundlePath);
|
|
abInfoV.SetAssetBundleSize(file.Length);
|
|
abInfoV.onLoaded(assetBundleName, bundle);
|
|
}
|
|
}));
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
|
|
#region AssetBundle 包的依赖相关
|
|
|
|
private IEnumerator GetAssetBundleDependency(string assetBundleName, Action action)
|
|
{
|
|
assetBundleName = assetBundleName.ToLower();
|
|
|
|
var allDependencies = new List<string>() { assetBundleName };
|
|
allDependencies.AddRange(GetABDependency(assetBundleName));
|
|
var index = 0;
|
|
CacheDependency(assetBundleName, allDependencies.ToArray());
|
|
var allDepends = allDependencies.Where(dependencyAbName => dependencyAbName != assetBundleName).ToList();
|
|
|
|
foreach (var dependencyAbName in allDepends)
|
|
{
|
|
yield return LoadDependencyAssetBundle(assetBundleName, dependencyAbName, delegate { index++; });
|
|
}
|
|
|
|
while (index != allDepends.Count)
|
|
{
|
|
yield return new WaitForEndOfFrame();
|
|
}
|
|
|
|
action?.Invoke();
|
|
}
|
|
|
|
private void GetAssetBundleDependency(string assetBundleName)
|
|
{
|
|
assetBundleName = assetBundleName.ToLower();
|
|
|
|
var allDependencies = new List<string>() { assetBundleName };
|
|
allDependencies.AddRange(GetABDependency(assetBundleName));
|
|
CacheDependency(assetBundleName, allDependencies.ToArray());
|
|
var allDepends = allDependencies.Where(dependencyAbName => dependencyAbName != assetBundleName).ToList();
|
|
|
|
foreach (var dependencyAbName in allDepends)
|
|
{
|
|
LoadDependencyAssetBundleSync(assetBundleName, dependencyAbName);
|
|
}
|
|
}
|
|
|
|
private IEnumerator LoadDependencyAssetBundle(string parentAssetBundleName, string assetBundleName,
|
|
UnityAction<AssetBundle> onCompleted)
|
|
{
|
|
assetBundleName = assetBundleName.ToLower();
|
|
var assetBundlePath = GenerateAssetBundlePath(assetBundleName, IsMD5Encrypt);
|
|
|
|
CrazyAsyKit.StopAction(assetBundleName + "Unload");
|
|
UnWaitUnload(assetBundleName);
|
|
|
|
if (IsCacheAssetBundle(assetBundleName))
|
|
{
|
|
CacheAssetBundle(assetBundleName, null, true);
|
|
var LoveLegendInfo = GetCacheAssetBundle(assetBundleName);
|
|
LoveLegendInfo?.callRes(parentAssetBundleName, onCompleted);
|
|
}
|
|
else
|
|
{
|
|
var LoveLegendInfo = new ZooMatchInfo(assetBundleName, onCompleted);
|
|
CacheAssetBundle(assetBundleName, LoveLegendInfo);
|
|
if (File.Exists(assetBundlePath))
|
|
{
|
|
yield return LoadABFromFileAsync(assetBundlePath, ZooMatchConstant.admsie,
|
|
delegate (AssetBundle bundle)
|
|
{
|
|
if (bundle == null)
|
|
{
|
|
Debug.LogError("加载AssetBundle 失败:" + assetBundleName);
|
|
UnCacheAssetBundle(assetBundleName);
|
|
}
|
|
else
|
|
{
|
|
GetCacheAssetBundle(assetBundleName).onLoaded(parentAssetBundleName, bundle);
|
|
}
|
|
});
|
|
}
|
|
else
|
|
{
|
|
CrazyAsyKit.StartCoroutine(LoadABFromFileAsync(assetBundlePath,
|
|
ZooMatchConstant.admsie, delegate (AssetBundle bundle)
|
|
{
|
|
if (bundle == null)
|
|
{
|
|
Debug.LogError("加载AssetBundle 失败:" + assetBundleName);
|
|
UnCacheAssetBundle(assetBundleName);
|
|
}
|
|
else
|
|
{
|
|
GetCacheAssetBundle(assetBundleName).onLoaded(parentAssetBundleName, bundle);
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
}
|
|
|
|
private AssetBundle LoadDependencyAssetBundleSync(string parentAssetBundleName, string assetBundleName)
|
|
{
|
|
assetBundleName = assetBundleName.ToLower();
|
|
var assetBundlePath = GenerateAssetBundlePath(assetBundleName, IsMD5Encrypt);
|
|
CrazyAsyKit.StopAction(assetBundleName + "Unload");
|
|
UnWaitUnload(assetBundleName);
|
|
|
|
if (IsCacheAssetBundle(assetBundleName))
|
|
{
|
|
CacheAssetBundle(assetBundleName, null, true);
|
|
var assetBundleInfos = GetCacheAssetBundle(assetBundleName);
|
|
return assetBundleInfos?.assetBundle;
|
|
}
|
|
|
|
var LoveLegendInfo = new ZooMatchInfo(assetBundleName, null);
|
|
CacheAssetBundle(assetBundleName, LoveLegendInfo);
|
|
if (File.Exists(assetBundlePath))
|
|
{
|
|
GetAssetBundleDependency(assetBundleName);
|
|
var assetBundle =
|
|
LoadDecryptAssetBundleSync(assetBundlePath, ZooMatchConstant.admsie);
|
|
LoveLegendInfo.assetBundle = assetBundle;
|
|
return assetBundle;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
|
|
private string[] GetABDependency(string assetBundleName)
|
|
{
|
|
assetBundleName = assetBundleName.ToLower();
|
|
return GetManifest().GetDirectDependencies(assetBundleName);
|
|
}
|
|
|
|
#region 依赖关系相关
|
|
|
|
private bool IsCacheDependency(string assetBundleName)
|
|
{
|
|
if (_cacheDependencyDict == null || _cacheDependencyDict.Count == 0) return false;
|
|
assetBundleName = assetBundleName.ToLower();
|
|
var isDependency = _cacheDependencyDict.ContainsKey(assetBundleName);
|
|
|
|
return isDependency;
|
|
}
|
|
|
|
|
|
private bool IsOtherDependency(string assetBundleName)
|
|
{
|
|
assetBundleName = assetBundleName.ToLower();
|
|
var isDependency = false;
|
|
if (_cacheDependencyDict == null || _cacheDependencyDict.Count == 0) return false;
|
|
foreach (var keyValuePair in _cacheDependencyDict)
|
|
{
|
|
isDependency = keyValuePair.Value.Contains(assetBundleName);
|
|
if (isDependency)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return isDependency;
|
|
}
|
|
|
|
private void CacheDependency(string assetBundleName, string[] assetBundleNameArray)
|
|
{
|
|
assetBundleName = assetBundleName.ToLower();
|
|
if (!IsCacheDependency(assetBundleName))
|
|
{
|
|
for (int i = 0; i < assetBundleNameArray.Length; i++)
|
|
{
|
|
assetBundleNameArray[i] = assetBundleNameArray[i].ToLower();
|
|
}
|
|
|
|
_cacheDependencyDict.Add(assetBundleName, assetBundleNameArray);
|
|
}
|
|
}
|
|
|
|
|
|
private void UnCacheDependency(string assetBundleName)
|
|
{
|
|
assetBundleName = assetBundleName.ToLower();
|
|
if (IsCacheDependency(assetBundleName))
|
|
{
|
|
_cacheDependencyDict.Remove(assetBundleName);
|
|
}
|
|
}
|
|
|
|
|
|
private string[] GetCacheDependency(string assetBundleName)
|
|
{
|
|
assetBundleName = assetBundleName.ToLower();
|
|
string[] dependencyList = { };
|
|
if (IsCacheDependency(assetBundleName))
|
|
{
|
|
dependencyList = _cacheDependencyDict[assetBundleName];
|
|
}
|
|
|
|
return dependencyList;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region 管理已加载的AssetBundle文件
|
|
|
|
private void CacheAssetBundle(string assetBundleName, ZooMatchInfo assetBundleInfoV,
|
|
bool isDependency = false)
|
|
{
|
|
assetBundleName = assetBundleName.ToLower();
|
|
if (IsCacheAssetBundle(assetBundleName))
|
|
{
|
|
if (isDependency)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_cacheAssetBundleInfoDict.Add(assetBundleName, assetBundleInfoV);
|
|
}
|
|
}
|
|
|
|
|
|
private void UnCacheAssetBundle(string assetBundleName)
|
|
{
|
|
if (IsCacheAssetBundle(assetBundleName))
|
|
{
|
|
_cacheAssetBundleInfoDict.Remove(assetBundleName.ToLower());
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
|
|
|
|
private ZooMatchInfo GetCacheAssetBundle(string assetBundleName)
|
|
{
|
|
ZooMatchInfo assetBundle = null;
|
|
if (IsCacheAssetBundle(assetBundleName))
|
|
{
|
|
assetBundle = _cacheAssetBundleInfoDict[assetBundleName.ToLower()];
|
|
}
|
|
else
|
|
{
|
|
}
|
|
|
|
return assetBundle;
|
|
}
|
|
|
|
|
|
private bool IsCacheAssetBundle(string assetBundleName)
|
|
{
|
|
assetBundleName = assetBundleName.ToLower();
|
|
if (_cacheAssetBundleInfoDict == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return _cacheAssetBundleInfoDict.ContainsKey(assetBundleName);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 卸载AssetBundle相关
|
|
|
|
#region 卸载AssetBundle相关信息管理
|
|
|
|
private bool WaitUnload(ZooMatchInfo assetBundleInfoV)
|
|
{
|
|
var isInWait = IsWaitUnload(assetBundleInfoV.assetBundleName);
|
|
if (isInWait) return true;
|
|
assetBundleInfoV.UpdateWaitUnloadCurrentTime();
|
|
_waitUnloadList.Add(assetBundleInfoV);
|
|
return false;
|
|
}
|
|
|
|
|
|
private bool IsWaitUnloadKey(string assetBundleName)
|
|
{
|
|
var isWaitUnload = false;
|
|
if (_waitUnloadList == null || _waitUnloadList.Count <= 0) return false;
|
|
foreach (var bundleInfo in _waitUnloadList)
|
|
{
|
|
if (bundleInfo == null || !string.IsNullOrEmpty(bundleInfo.assetBundleName)) continue;
|
|
if (!bundleInfo.assetBundleName.Equals(assetBundleName)) continue;
|
|
isWaitUnload = true;
|
|
break;
|
|
}
|
|
|
|
return isWaitUnload;
|
|
}
|
|
|
|
|
|
private bool IsWaitUnload(string assetBundleName)
|
|
{
|
|
var isWaitUnload = false;
|
|
if (_waitUnloadList == null || _waitUnloadList.Count == 0) return false;
|
|
if (!IsWaitUnloadKey(assetBundleName))
|
|
{
|
|
foreach (var waitUnloadAssetBundle in _waitUnloadList)
|
|
{
|
|
if (waitUnloadAssetBundle == null ||
|
|
!string.IsNullOrEmpty(waitUnloadAssetBundle.assetBundleName)) continue;
|
|
isWaitUnload = GetABDependency(waitUnloadAssetBundle.assetBundleName).Contains(assetBundleName);
|
|
if (isWaitUnload)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
isWaitUnload = true;
|
|
}
|
|
|
|
return isWaitUnload;
|
|
}
|
|
|
|
|
|
private bool UnWaitUnload(string assetBundleName)
|
|
{
|
|
var isRemove = false;
|
|
|
|
foreach (var bundleInfo in _waitUnloadList)
|
|
{
|
|
if (bundleInfo == null) continue;
|
|
if (!bundleInfo.assetBundleName.Equals(assetBundleName)) continue;
|
|
isRemove = _waitUnloadList.Remove(bundleInfo);
|
|
break;
|
|
}
|
|
|
|
return isRemove;
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
public void UnloadAssetBundle(string assetBundleName,
|
|
bool ignoreDependency = false,
|
|
int unloadWaitTime = 0,
|
|
Action<bool> onCompleted = null)
|
|
{
|
|
if (string.IsNullOrEmpty(assetBundleName))
|
|
{
|
|
onCompleted?.Invoke(false);
|
|
return;
|
|
}
|
|
|
|
bool unloadSucceed;
|
|
if (IsCacheAssetBundle(assetBundleName))
|
|
{
|
|
var abInfo = GetCacheAssetBundle(assetBundleName);
|
|
if (abInfo == null)
|
|
{
|
|
onCompleted?.Invoke(false);
|
|
return;
|
|
}
|
|
|
|
|
|
if (WaitUnload(abInfo) && !ignoreDependency)
|
|
{
|
|
unloadSucceed = false;
|
|
|
|
UnCacheDependency(assetBundleName);
|
|
|
|
onCompleted?.Invoke(unloadSucceed);
|
|
}
|
|
else
|
|
{
|
|
CrazyAsyKit.StopAction(assetBundleName + "Unload");
|
|
CrazyAsyKit.StartAction(assetBundleName + "Unload", delegate
|
|
{
|
|
unloadSucceed = IsCacheAssetBundle(assetBundleName) &&
|
|
UnloadAssetBundleInternal(assetBundleName, ignoreDependency);
|
|
|
|
UnWaitUnload(assetBundleName);
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
#endif
|
|
|
|
onCompleted?.Invoke(unloadSucceed);
|
|
}, unloadWaitTime);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
onCompleted?.Invoke(false);
|
|
}
|
|
}
|
|
|
|
|
|
private bool UnloadAssetBundleInternal(string assetBundleName, bool isIgnoreDependency = false,
|
|
bool isThorough = false)
|
|
{
|
|
var LoveLegendInfo = GetCacheAssetBundle(assetBundleName);
|
|
if (LoveLegendInfo == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
var dependencyArray = GetCacheDependency(assetBundleName);
|
|
|
|
|
|
UnCacheDependency(assetBundleName);
|
|
|
|
|
|
if (!isIgnoreDependency)
|
|
{
|
|
if (IsOtherDependency(assetBundleName))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
UnCacheAssetBundle(assetBundleName);
|
|
|
|
|
|
LoveLegendInfo.Unload(isThorough);
|
|
|
|
|
|
foreach (var dependencyAssetBundleName in dependencyArray)
|
|
{
|
|
if (dependencyAssetBundleName == assetBundleName)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
if (!IsOtherDependency(dependencyAssetBundleName))
|
|
{
|
|
UnloadAssetBundleInternal(dependencyAssetBundleName, false, isThorough);
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region 封装直接加载资源的方法
|
|
|
|
public T GetAsset<T>(string assetBundleName, string assetName) where T : Object
|
|
{
|
|
var assetBundlePath = GenerateAssetBundlePath(assetBundleName);
|
|
var assetBundle = GetAssetBundle(assetBundlePath, assetBundleName);
|
|
|
|
return assetBundle.LoadAsset<T>(assetName);
|
|
}
|
|
|
|
|
|
public void GetAsset<T>(string assetBundleName, string assetName, UnityAction<T> onCompleted) where T : Object
|
|
{
|
|
LoadAssetInternal(assetBundleName, delegate (AssetBundle bundle)
|
|
{
|
|
if (bundle == null)
|
|
{
|
|
Debug.LogError("加载AssetBundle 失败:" + assetBundleName);
|
|
}
|
|
else
|
|
{
|
|
CrazyAsyKit.StartCoroutine(LoadAssetFromAssetBundle(bundle, assetName, onCompleted));
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
public void InitManifest(string assetBundleManifestName, UnityAction<bool> onCompleted)
|
|
{
|
|
CrazyAsyKit.StopAction(assetBundleManifestName + "Unload");
|
|
if (UnWaitUnload(assetBundleManifestName))
|
|
{
|
|
}
|
|
var assetBundles =
|
|
AssetBundle.LoadFromFile($"{ZooMatchFileKit.GetFilePath()}{ZooMatchConstant.undles}");
|
|
var manifest = assetBundles.LoadAsset<AssetBundleManifest>("assetbundlemanifest");
|
|
_manifest = manifest;
|
|
onCompleted?.Invoke(manifest != null);
|
|
}
|
|
|
|
#endregion
|
|
|
|
public void RecycleAssetBundle(string assetBundleName, UnityAction onCompleted = null)
|
|
{
|
|
if (IsCacheAssetBundle(assetBundleName))
|
|
{
|
|
var abInfo = GetCacheAssetBundle(assetBundleName);
|
|
abInfo.UnReferenced(assetBundleName);
|
|
|
|
RecycleAssetBundleDependency(assetBundleName, UnloadWaitTime);
|
|
|
|
if (abInfo.GetReferenced() <= 0)
|
|
{
|
|
UnloadAssetBundle(assetBundleName, false, UnloadWaitTime);
|
|
}
|
|
}
|
|
|
|
onCompleted?.Invoke();
|
|
}
|
|
|
|
private void RecycleAssetBundleDependency(string abName, int waitTime)
|
|
{
|
|
var otherAbName = GetCacheDependency(abName);
|
|
if (otherAbName.Length <= 0) return;
|
|
foreach (var dependAbName in otherAbName)
|
|
{
|
|
if (dependAbName == abName) continue;
|
|
var dependAbInfo = GetCacheAssetBundle(dependAbName);
|
|
if (dependAbInfo == null) continue;
|
|
dependAbInfo.UnReferenced(abName);
|
|
|
|
|
|
if (dependAbInfo.GetReferenced() <= 0)
|
|
{
|
|
UnloadAssetBundle(dependAbName, false, waitTime);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#region 其他方法
|
|
|
|
private string GenerateAssetBundlePath(string assetBundleName, bool isMD5 = false, bool isManifest = false,
|
|
bool isAddABSuffix = true)
|
|
{
|
|
var fileName = assetBundleName.ToLower();
|
|
if (isMD5)
|
|
{
|
|
fileName = MD5String(fileName) + ".data";
|
|
}
|
|
|
|
var filePath = _assetBundleRootPath.Replace("file:///", "") + assetBundleName.ToLower();
|
|
if (isAddABSuffix)
|
|
{
|
|
filePath += ZooMatchConstant.setbun;
|
|
}
|
|
|
|
if (!isManifest)
|
|
return filePath;
|
|
if (File.Exists(filePath))
|
|
{
|
|
return filePath;
|
|
}
|
|
|
|
return filePath;
|
|
}
|
|
|
|
private static string MD5String(string str)
|
|
{
|
|
using var md5 = MD5.Create();
|
|
var hash = md5.ComputeHash(Encoding.GetEncoding("utf-8").GetBytes(str));
|
|
var tmp = new StringBuilder();
|
|
foreach (var i in hash)
|
|
{
|
|
tmp.Append(i.ToString("x2"));
|
|
}
|
|
|
|
return tmp.ToString();
|
|
}
|
|
|
|
#endregion
|
|
|
|
public void RecycleAsset(string assetUrl, UnityAction onCompleted)
|
|
{
|
|
RecycleAssetBundle(assetUrl, onCompleted);
|
|
}
|
|
|
|
private AssetBundleManifest GetManifest()
|
|
{
|
|
if (_manifest == null)
|
|
{
|
|
Debug.LogError("AssetBundleManifest is null");
|
|
var assetBundles =
|
|
AssetBundle.LoadFromFile($"{ZooMatchFileKit.GetFilePath()}{ZooMatchConstant.undles}");
|
|
var manifest = assetBundles.LoadAsset<AssetBundleManifest>("assetbundlemanifest");
|
|
_manifest = manifest;
|
|
}
|
|
|
|
return _manifest;
|
|
}
|
|
}
|
|
} |