using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cysharp.Threading.Tasks;
///
/// [Obsolete] US1: 已被 YooAssetService 替代。将在 Phase 10 (T060) 物理删除。
/// 当前仍保留以支持 AssetBundleInitTask 的启动兼容性。
///
[System.Obsolete("Use ProjSG.Resource.YooAssetService instead. This class will be removed in Phase 10 (T060).")]
public class AssetBundleUtility : SingletonMonobehaviour
{
private List m_AssetBundleInfoList = new List();
private List m_LoadingAssetBundleList = new List();
private List m_LoadingAssetList = new List();
private Dictionary m_AssetInfoDict = new Dictionary();
private Dictionary m_AssetBundleDict = new Dictionary();
private Dictionary> m_AssetDict = new Dictionary>();
public bool initialized { get; private set; }
public bool initializedUIAssetBundle { get; private set; }
public void InitBuiltInAsset()
{
var path = AssetVersionUtility.GetBuiltInAssetFilePath(StringUtility.Concat(AssetVersionUtility.EncodeFileName("builtin"), "_assetbundle"), false);
var assetBundle = AssetBundle.LoadFromFile(path);
if (assetBundle == null)
{
Debug.LogErrorFormat("AssetBundleManifest的包文件为空或者加载出错. Path:{0}", path);
}
var manifest = assetBundle.LoadAsset(ResourcesPath.AssetDependentFileAssetName);
if (manifest == null)
{
Debug.LogErrorFormat("AssetBundleManifest的包文件为空或者加载出错. Path:{0}", path);
}
var bundles = manifest.GetAllAssetBundles();
foreach (var bundle in bundles)
{
var dependenices = manifest.GetAllDependencies(bundle);
var hash = manifest.GetAssetBundleHash(bundle);
var assetBundleInfo = new AssetBundleInfo(bundle, hash, dependenices);
m_AssetBundleInfoList.Add(assetBundleInfo);
}
assetBundle.Unload(true);
assetBundle = null;
}
public void ReInitBuiltInAsset()
{
// WindowConfig.Release();
// CloseAllIgnoreWindowConfig.Release();
UnloadAssetBundle("builtin/scriptableobjects", true, false);
var path = AssetVersionUtility.GetBuiltInAssetFilePath(StringUtility.Concat(AssetVersionUtility.EncodeFileName("builtin"), "_assetbundle"), false);
var assetBundle = AssetBundle.LoadFromFile(path);
if (assetBundle == null)
{
Debug.LogErrorFormat("AssetBundleManifest的包文件为空或者加载出错. Path:{0}", path);
}
var manifest = assetBundle.LoadAsset(ResourcesPath.AssetDependentFileAssetName);
if (manifest == null)
{
Debug.LogErrorFormat("AssetBundleManifest的包文件为空或者加载出错. Path:{0}", path);
}
for (int i = m_AssetBundleInfoList.Count - 1; i >= 0; i--)
{
var item = m_AssetBundleInfoList[i];
if (item.name.Contains("builtin"))
{
m_AssetBundleInfoList.Remove(item);
}
}
var keys = new List(m_AssetBundleDict.Keys);
for (int i = keys.Count - 1; i >= 0; i--)
{
var item = keys[i];
if (item.Contains("builtin"))
{
m_AssetBundleDict[item].Unload(false);
m_AssetBundleDict.Remove(item);
}
}
var bundles = manifest.GetAllAssetBundles();
foreach (var bundle in bundles)
{
var dependenices = manifest.GetAllDependencies(bundle);
var hash = manifest.GetAssetBundleHash(bundle);
var assetBundleInfo = new AssetBundleInfo(bundle, hash, dependenices);
m_AssetBundleInfoList.Add(assetBundleInfo);
}
assetBundle.Unload(true);
assetBundle = null;
}
public async UniTask Initialize()
{
await UniTask.Delay(200);
await Co_LoadMainfestFile("audio");
// await Co_LoadMainfestFile("video");
await Co_LoadMainfestFile("mobeffectshader");
await Co_LoadMainfestFile("config");
await Co_LoadMainfestFile("maps");
await Co_LoadMainfestFile("ui");
await Co_LoadAssetBundle(ResourcesPath.windowFileBundleName);
await Co_LoadAssetBundle(ResourcesPath.uiprefabFileBundleName);
initializedUIAssetBundle = true;
initialized = true;
}
private UniTask Co_LoadMainfestFile(string _category)
{
var path = AssetVersionUtility.GetAssetFilePath(StringUtility.Concat(AssetVersionUtility.EncodeFileName(_category), "_assetbundle"), false);
var _assetBundle = AssetBundle.LoadFromFile(path);
if (_assetBundle == null)
{
Debug.LogErrorFormat("AssetBundleManifest的包文件为空或者加载出错. Path:{0}", path);
return UniTask.CompletedTask;
}
AssetBundleManifest _assetBundleManifest = _assetBundle.LoadAsset(ResourcesPath.AssetDependentFileAssetName);
if (_assetBundleManifest == null)
{
Debug.LogErrorFormat("AssetBundleManifest的包文件为空或者加载出错. Path:{0}", path);
return UniTask.CompletedTask;
}
string[] _assetBundleNames = _assetBundleManifest.GetAllAssetBundles();
foreach (var _assetBundleName in _assetBundleNames)
{
string[] _dependenices = _assetBundleManifest.GetAllDependencies(_assetBundleName);
Hash128 _hash = _assetBundleManifest.GetAssetBundleHash(_assetBundleName);
AssetBundleInfo _assetBundleInfo = new AssetBundleInfo(_assetBundleName, _hash, _dependenices);
m_AssetBundleInfoList.Add(_assetBundleInfo);
}
_assetBundle.Unload(true);
_assetBundle = null;
return UniTask.CompletedTask;
}
public AssetBundleInfo GetAssetBundleInfo(string assetBundleName)
{
return m_AssetBundleInfoList.Find((x) => { return x.name == assetBundleName; });
}
#region 对AssetBundle资源进行异步协程加载的方法
public void Co_LoadAsset(AssetInfo assetInfo, Action callBack = null)
{
Co_LoadAsset(assetInfo.assetBundleName, assetInfo.name, callBack);
}
public void Co_LoadAsset(string assetBundleName, string assetName, Action callBack = null)
{
#if UNITY_5||UNITY_5_3_OR_NEWER
assetBundleName = assetBundleName.ToLower();
#endif
if (JudgeExistAsset(assetBundleName, assetName))
{
if (callBack != null)
{
callBack(true, m_AssetDict[assetBundleName][assetName]);
}
return;
}
Co_DoLoadAsset(assetBundleName, assetName, callBack).Forget();
}
private async UniTask Co_LoadAssetBundle(string assetBundleName)
{
#if UNITY_5||UNITY_5_3_OR_NEWER
assetBundleName = assetBundleName.ToLower();
#endif
if (JudgeExistAssetBundle(assetBundleName))
{
return m_AssetBundleDict[assetBundleName];
}
if (m_LoadingAssetBundleList.Contains(assetBundleName))
{
while (!m_AssetBundleDict.ContainsKey(assetBundleName))
{
// Debug.Log(Time.frameCount + " ] 正在加载AssetBundle: " + assetBundleName + ", 请等待...");
await UniTask.Yield();
}
return m_AssetBundleDict[assetBundleName];
}
m_LoadingAssetBundleList.Add(assetBundleName);
var _assetBundleInfo = GetAssetBundleInfo(assetBundleName);
if (_assetBundleInfo == null)
{
Debug.LogErrorFormat("Co_LoadAssetBundle(): {0}出现错误 => 不存在AssetBundleInfo. ", assetBundleName);
m_LoadingAssetBundleList.Remove(assetBundleName);
return null;
}
if (_assetBundleInfo.dependentBundles.Length > 0)
{
await Co_LoadAssetBundleDependenice(_assetBundleInfo);
}
var isBuiltin = assetBundleName.Contains("builtin");
var filePath = isBuiltin ? AssetVersionUtility.GetBuiltInAssetFilePath(assetBundleName) : AssetVersionUtility.GetAssetFilePath(assetBundleName);
Debug.LogFormat("Co_LoadAssetBundle(): 将要加载的assetBundle包路径 => {0}", filePath);
var _request = AssetBundle.LoadFromFileAsync(filePath);
await _request;
CacheAssetBundle(assetBundleName, _request.assetBundle);
m_LoadingAssetBundleList.Remove(assetBundleName);
return _request.assetBundle;
}
private async UniTask Co_LoadAssetBundleDependenice(AssetBundleInfo assetBundleInfo)
{
AssetBundle _assetBundle = null;
if (assetBundleInfo.dependentBundles == null
|| assetBundleInfo.dependentBundles.Length == 0)
{
return;
}
for (int i = 0; i < assetBundleInfo.dependentBundles.Length; ++i)
{
if (m_AssetBundleDict.TryGetValue(assetBundleInfo.dependentBundles[i], out _assetBundle) == false)
{
await Co_LoadAssetBundle(assetBundleInfo.dependentBundles[i]);
}
else
{
if (_assetBundle == null)
{
await Co_LoadAssetBundle(assetBundleInfo.dependentBundles[i]);
}
}
}
}
private async UniTask Co_DoLoadAsset(string assetBundleName, string assetName, Action callBack = null)
{
#if UNITY_5||UNITY_5_3_OR_NEWER
assetBundleName = assetBundleName.ToLower();
#endif
#if UNITY_EDITOR
RunTimeABLoadLog.AddLog(assetBundleName, assetName, UnityEngine.SceneManagement.SceneManager.GetActiveScene().name);
#endif
await Co_LoadAssetBundle(assetBundleName);
if (!m_AssetBundleDict.ContainsKey(assetBundleName))
{
if (callBack != null)
{
callBack(false, null);
}
return;
}
string _checkTag = assetBundleName + "@" + assetName;
if (m_LoadingAssetList.Contains(_checkTag))
{
while (!m_AssetDict.ContainsKey(assetBundleName)
|| !m_AssetDict[assetBundleName].ContainsKey(assetName))
{
// Debug.Log(Time.frameCount + " ] 正在加载Asset: " + _checkTag + ", 请等待...");
await UniTask.Yield();
}
if (callBack != null)
{
callBack(true, m_AssetDict[assetBundleName][assetName]);
}
return;
}
m_LoadingAssetList.Add(_checkTag);
var request = m_AssetBundleDict[assetBundleName].LoadAssetAsync(assetName);
await request;
if (request.asset != null)
{
CacheAsset(assetBundleName, assetName, request.asset);
if (callBack != null)
{
callBack(true, m_AssetDict[assetBundleName][assetName]);
}
}
else
{
if (callBack != null)
{
callBack(false, null);
}
}
m_LoadingAssetList.Remove(_checkTag);
}
private async UniTask Co_DoLoadAsset(AssetInfo assetInfo, Action callBack = null)
{
if (assetInfo == null)
{
Debug.LogErrorFormat("Co_DoLoadAsset(): {0}, 出现错误 => 存入的AssetInfo为null. ", assetInfo);
return;
}
await Co_DoLoadAsset(assetInfo.assetBundleName, assetInfo.name, callBack);
}
#endregion
#region 对AssetBundle资源进行同步加载的方法
public void Sync_LoadAll(string assetBundleName)
{
if (JudgeExistAssetBundle(assetBundleName))
{
return;
}
#if UNITY_5||UNITY_5_3_OR_NEWER
assetBundleName = assetBundleName.ToLower();
#endif
Sync_LoadAssetBundle(assetBundleName);
}
public void Sync_LoadAllAssets(string assetBundleName)
{
if (JudgeExistAssetBundle(assetBundleName))
{
return;
}
#if UNITY_5||UNITY_5_3_OR_NEWER
assetBundleName = assetBundleName.ToLower();
#endif
Sync_LoadAssetBundle(assetBundleName);
if (m_AssetBundleDict.ContainsKey(assetBundleName))
{
var assetBundle = m_AssetBundleDict[assetBundleName];
assetBundle.LoadAllAssets();
}
}
public UnityEngine.Object Sync_LoadAsset(AssetInfo assetInfo, Type _type = null)
{
return Sync_LoadAsset(assetInfo.assetBundleName, assetInfo.name, _type);
}
public UnityEngine.Object Sync_LoadAsset(string assetBundleName, string assetName, Type _type = null)
{
if (string.IsNullOrEmpty(assetName))
{
Debug.LogErrorFormat("Sync_LoadAsset(): {0}, 出现错误 => 存入的AssetName为null. ", assetName);
return null;
}
#if UNITY_5||UNITY_5_3_OR_NEWER
assetBundleName = assetBundleName.ToLower();
#endif
UnityEngine.Object _object = null;
if (JudgeExistAsset(assetBundleName, assetName))
{
_object = m_AssetDict[assetBundleName][assetName];
}
else
{
#if UNITY_EDITOR
RunTimeABLoadLog.AddLog(assetBundleName, assetName, UnityEngine.SceneManagement.SceneManager.GetActiveScene().name);
#endif
Sync_LoadAssetBundle(assetBundleName);
if (m_AssetBundleDict.ContainsKey(assetBundleName))
{
if (_type != null)
{
_object = m_AssetBundleDict[assetBundleName].LoadAsset(assetName, _type);
}
else
{
_object = m_AssetBundleDict[assetBundleName].LoadAsset(assetName);
}
if (_object != null)
{
CacheAsset(assetBundleName, assetName, _object);
}
}
}
if (_object == null)
{
Debug.LogErrorFormat("Sync_LoadAsset(): {0} 出现错误 => null. ", assetName);
}
return _object;
}
private void Sync_LoadAssetBundle(string assetBundleName)
{
if (JudgeExistAssetBundle(assetBundleName))
{
return;
}
AssetBundleInfo _assetBundleInfo = GetAssetBundleInfo(assetBundleName);
if (_assetBundleInfo == null)
{
Debug.LogErrorFormat("Sync_LoadAssetBundle(): {0} 出现错误 => 不存在AssetBundleInfo. ", assetBundleName);
return;
}
Sync_LoadAssetBundleDependenice(_assetBundleInfo);
var isBuiltin = assetBundleName.Contains("builtin");
string _path = isBuiltin ? AssetVersionUtility.GetBuiltInAssetFilePath(assetBundleName) : AssetVersionUtility.GetAssetFilePath(assetBundleName);
Debug.LogFormat("Sync_LoadAssetBundle(): {0} => {1}", assetBundleName, _path);
AssetBundle _assetBundle = AssetBundle.LoadFromFile(_path);
CacheAssetBundle(assetBundleName, _assetBundle);
}
private void Sync_LoadAssetBundleDependenice(AssetBundleInfo assetBundleInfo)
{
if (assetBundleInfo.dependentBundles == null
|| assetBundleInfo.dependentBundles.Length == 0)
{
return;
}
AssetBundle _assetBundle = null;
for (int i = 0; i < assetBundleInfo.dependentBundles.Length; ++i)
{
if (m_AssetBundleDict.TryGetValue(assetBundleInfo.dependentBundles[i], out _assetBundle) == false)
{
Sync_LoadAssetBundle(assetBundleInfo.dependentBundles[i]);
}
else
{
if (_assetBundle == null)
{
Sync_LoadAssetBundle(assetBundleInfo.dependentBundles[i]);
}
}
}
}
#endregion
#region 对AssetBundle资源进行异步线程加载的方法
#endregion
#region AssetBundle资源卸载方法
public void UnloadAssetBundle(string assetBundleName, bool unloadAllLoadedObjects, bool includeDependenice)
{
#if UNITY_5||UNITY_5_3_OR_NEWER
assetBundleName = assetBundleName.ToLower();
#endif
if (JudgeExistAssetBundle(assetBundleName) == false)
{
Debug.LogWarningFormat("UnloadAssetBundle(): 要卸载的包不在缓存中或者已经被卸载 => {0}. ", assetBundleName);
return;
}
AssetBundleInfo _assetBundleInfo = GetAssetBundleInfo(assetBundleName);
UnloadAssetBundle(_assetBundleInfo, unloadAllLoadedObjects, includeDependenice);
}
public void UnloadAsset(string assetBundleName, string assetName)
{
#if UNITY_5||UNITY_5_3_OR_NEWER
assetBundleName = assetBundleName.ToLower();
#endif
string _assembleName = StringUtility.Concat(assetBundleName, "@", assetName);
if (JudgeExistAsset(assetBundleName, assetName) == false)
{
Debug.LogWarningFormat("UnloadAsset(): 要卸载的资源不在缓存中 => {0}. ", _assembleName);
return;
}
UnityEngine.Object _assetObject = m_AssetDict[assetBundleName][assetName];
m_AssetDict[assetBundleName].Remove(assetName);
if (_assetObject is GameObject)
{
Debug.LogFormat("UnloadAsset(): 成功卸载asset资源 => {0}. 类型为{1}, 不做其他处理. ", assetName, _assetObject.GetType().Name);
}
else
{
Resources.UnloadAsset(_assetObject);
Debug.LogFormat("UnloadAsset(): 成功卸载asset资源 => {0}. 类型为{1}, 执行Resources.UnloadAsset(). ", assetName, _assetObject.GetType().Name);
}
if (Application.isEditor)
{
Transform _asset = transform.Find(assetBundleName + "/Asset:" + assetName);
if (_asset)
{
Destroy(_asset.gameObject);
}
}
}
public void UnloadAsset(AssetInfo assetInfo)
{
UnloadAsset(assetInfo.assetBundleName, assetInfo.name);
}
public void UnloadAll()
{
List _assetBundleNameList = new List(m_AssetBundleDict.Keys);
foreach (var _assetBundleName in _assetBundleNameList)
{
UnloadAssetBundle(_assetBundleName, true, true);
}
}
private void UnloadAssetBundle(AssetBundleInfo assetBundleInfo, bool unloadAllLoadedObjects, bool includeDependenice)
{
// 是否卸载依赖资源
if (includeDependenice)
{
if (assetBundleInfo.dependentBundles != null
&& assetBundleInfo.dependentBundles.Length > 0)
{
for (int i = 0; i < assetBundleInfo.dependentBundles.Length; ++i)
{
UnloadAssetBundle(assetBundleInfo.dependentBundles[i], unloadAllLoadedObjects, includeDependenice);
}
}
}
if (m_AssetDict.ContainsKey(assetBundleInfo.name))
{
List _assetNames = new List(m_AssetDict[assetBundleInfo.name].Keys);
// 卸载对应缓存住的asset资源
foreach (var _assetName in _assetNames)
{
UnloadAsset(assetBundleInfo.name, _assetName);
}
m_AssetDict.Remove(assetBundleInfo.name);
}
else
{
Debug.LogFormat("UnloadAssetBundle(): 要卸载assetBundle包 {0} 没有资源被加载. ", assetBundleInfo.name);
}
// assetBundle包卸载
m_AssetBundleDict[assetBundleInfo.name].Unload(unloadAllLoadedObjects);
//m_AssetDict.Remove(assetBundleInfo.name);
// 卸载缓存的assetBundle资源
m_AssetBundleDict.Remove(assetBundleInfo.name);
Debug.LogFormat("UnloadAssetBundle(): 成功卸载assetBundle包 => {0}. ", assetBundleInfo.name);
if (Application.isEditor)
{
Transform _asset = transform.Find(assetBundleInfo.name);
Transform _parent = _asset.parent;
if (_asset)
{
DestroyImmediate(_asset.gameObject);
}
if (_parent.childCount == 0 && _parent != transform)
{
DestroyImmediate(_parent.gameObject);
}
}
}
#endregion
public bool JudgeExistAsset(string assetBundleName, string assetName)
{
#if UNITY_5||UNITY_5_3_OR_NEWER
assetBundleName = assetBundleName.ToLower();
#endif
if (string.IsNullOrEmpty(assetBundleName)
|| string.IsNullOrEmpty(assetName))
{
return false;
}
if (JudgeExistAssetBundle(assetBundleName) == false)
{
return false;
}
if (m_AssetDict.ContainsKey(assetBundleName) == false
|| m_AssetDict[assetBundleName].ContainsKey(assetName) == false
|| m_AssetDict[assetBundleName][assetName] == null)
{
return false;
}
return true;
}
public bool JudgeExistAssetBundle(string assetBundleName)
{
assetBundleName = assetBundleName.ToLower();
if (m_AssetBundleDict.ContainsKey(assetBundleName) == false)
{
return false;
}
if (m_AssetBundleDict[assetBundleName] == null)
{
return false;
}
return true;
}
private void CacheAsset(string assetBundleName, string assetName, UnityEngine.Object asset)
{
if (asset == null)
{
return;
}
if (asset is GameObject)
{
(asset as GameObject).SetActive(true);
}
if (m_AssetDict.ContainsKey(assetBundleName) == false)
{
Dictionary _temp = new Dictionary();
m_AssetDict.Add(assetBundleName, _temp);
}
m_AssetDict[assetBundleName][assetName] = asset;
string _assembleName = StringUtility.Concat(assetBundleName, "@", assetName);
if (m_AssetInfoDict.ContainsKey(_assembleName) == false)
{
AssetInfo _assetInfo = new AssetInfo(assetBundleName, assetName);
m_AssetInfoDict[_assembleName] = _assetInfo;
}
Debug.LogFormat("CacheAsset(): 成功缓存asset => {0}. ", assetName);
// if (Application.isEditor)
// {
// GameObject _go = new GameObject("Asset:" + assetName);
// Transform _parent = transform.Find(assetBundleName);
// if (_parent)
// {
// _go.transform.SetParent(_parent);
// }
// }
}
private void CacheAssetBundle(string assetBundleName, AssetBundle assetBundle)
{
if (assetBundle == null)
{
Debug.LogErrorFormat("CacheAssetBundle(): {0}出现错误 => 将要缓存的包为 null. ", assetBundleName);
return;
}
if (m_AssetBundleDict.ContainsKey(assetBundleName))
{
Debug.LogErrorFormat("CacheAssetBundle(): {0}出现错误 => 将要缓存的包已经在缓存中. ", assetBundleName);
return;
}
m_AssetBundleDict[assetBundleName] = assetBundle;
if (Application.isEditor)
{
string[] _names = assetBundleName.Split('/');
string _selfPath = string.Empty;
string _parentPath = string.Empty;
for (int i = 0; i < _names.Length; ++i)
{
_selfPath = _names[0];
for (int j = 1; j <= i; ++j)
{
_selfPath = _selfPath + "/" + _names[j];
}
if (transform.Find(_selfPath))
{
continue;
}
GameObject _go = new GameObject(_names[i]);
if (i == 0)
{
_go.transform.parent = transform;
}
else
{
_parentPath = _names[0];
for (int j = 1; j < i; ++j)
{
_parentPath = _parentPath + "/" + _names[j];
}
Transform _parent = transform.Find(_parentPath);
if (_parent)
{
_go.transform.parent = _parent;
}
}
}
}
Debug.LogFormat("CacheAssetBundle(): 成功缓存assetBundle包资源 => {0}. 目前有 {1} 个资源.", assetBundleName, m_AssetBundleDict.Count);
}
}