1221 lines
41 KiB
C#
Raw Normal View History

2024-08-23 15:49:34 +08:00
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using AssetManagement;
using AssetUpdate;
using GCGame.Table;
using Module.Log;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using System.Linq;
using Object = UnityEngine.Object;
#if UNITY_EDITOR
using UnityEditor;
using System.Runtime.Serialization.Formatters.Binary;
#endif
public class LoadAssetBundle : MonoBehaviour
{
#region Load Asset -
public const string atlasPathConvertTable = "AtlasPathConvert";
public const string BUNDLE_MAIN_BASE_UI = "MainBase";
public const string BUNDLE_PATH_MODEL = "model/";
public const string BUNDLE_PATH_PET = "model/";
public const string BUNDLE_PATH_EFFECT = "effect/";
public const string BUNDLE_PATH_UI = "ui/";
public const string BUNDLE_PATH_SOUND = "sounds/";
public const string BUNDLE_PATH_SPRITE = "ui/sprite/commonitem";
public const string BUNDLE_PATH_Other = "other/";
2024-08-23 15:49:34 +08:00
public const string bundleFileExtension = AssetConst.bundleVariant;
public const string BUNDLE_PATH_GAMERES = "gameres";
// 无用的Bundle仅仅用于打包时让Unity可以正常收集Shader之类的资源引用
public const string BUNDLE_PATH_DUMMY = "dummy";
// CommonItem的Bundle名称 - 原位于Editor程序集ClassifyBundles
public const string uiCommonSpriteBundle = uiSpriteBundleHeader + "commonitem";
// Sprite类Bundle名称头 - 原位于Editor程序集ClassifyBundles
public const string uiSpriteBundleHeader = "ui/sprite/";
private readonly LoadAssetRequestList<GameObject> _gameObjectList = new LoadAssetRequestList<GameObject>();
private readonly LoadAssetRequestList<Object> _assetList = new LoadAssetRequestList<Object>();
private readonly LoadAssetRequestList<AudioClip> _audioList = new LoadAssetRequestList<AudioClip>();
private readonly LoadAssetRequestList<TextAsset> _textAssetList = new LoadAssetRequestList<TextAsset>();
2024-08-23 15:49:34 +08:00
private readonly LoadSpriteRequestList _spriteList = new LoadSpriteRequestList();
2024-08-23 15:49:34 +08:00
private readonly LoadRawImageRequestList _rawImageList = new LoadRawImageRequestList();
public AssetPathHub pathHub { get; private set; }
// Use this for initialization
private void Awake()
{
Instance = this;
if (!AssetUpdateManager.useResources)
{
// 暂时不考虑动态切换资源路径的流程,需要再处理类型情况
pathHub = new AssetPathHub();
// 加载全部资源资料
string uri;
if (string.IsNullOrEmpty(AssetUpdateManager.assetUri))
{
Debug.LogError("Cannot find assetInfo. You should start the game from AssetUpdate instead of Login!");
// 这个问题无法正确恢复,仅仅测试版本可以继续使用本地资源
uri = string.Empty;
}
else
{
uri = AssetUpdateManager.assetUri;
}
var dependencyPath =
AssetConst.persistentDataPath.Open(AssetUtils.GetTextMd5(AssetConst.versionFile) +
AssetConst.bundleVariant);
2024-08-23 15:49:34 +08:00
AssetDependencyInfo dependencyInfo = null;
if (!File.Exists(dependencyPath))
{
Debug.LogError(
"Cannot find dependency file. You should start the game from AssetUpdate instead of Login!");
2024-08-23 15:49:34 +08:00
}
else
dependencyInfo = AssetDependencyInfo.Create(dependencyPath);
Debug.Log("LoaderAssetsBundle");
2024-08-23 15:49:34 +08:00
if (dependencyInfo == null)
{
Debug.LogError("Unable to load dependency file! This is not recoverable!");
LiteConfirmWin.Open("资源错误", "无法加载资源依赖!\n需要重启游戏修复",
new LiteConfirmButtonData("确定", () => SdkControl.instance.CloseGame()));
2024-08-23 15:49:34 +08:00
}
else
{
pathHub.Init(uri, dependencyInfo);
var loadHub = new BundleLoadHub();
// 暂时限制到同时5个并行加载
loadHub.Init(pathHub, new List<AsyncLoadRule>
{
new AsyncLoadRule(int.MaxValue, 5)
});
var downloadHub = new BundleDownloadHub();
// 后台下载限制到最大一个;主动加载限制到最大三个;
downloadHub.Init(pathHub, new List<AsyncLoadRule>
{
new AsyncLoadRule(0, 1),
2024-08-23 15:49:34 +08:00
new AsyncLoadRule(int.MaxValue, 3)
});
downloadHub.onComplete += pathHub.DownloadComplete;
// 注BundleManager需要在PathHub绑定后执行初始化否则无法正确更新PathData
var bundleManager = new BundleManager(pathHub, loadHub, downloadHub);
if (AssetManager.instance == null)
AssetManager.CreateInstance();
var assetManager = AssetManager.instance;
// ReSharper disable once PossibleNullReferenceException
assetManager.Init(bundleManager);
}
}
2024-08-23 15:49:34 +08:00
DontDestroyOnLoad(gameObject);
}
public void StartBackGround()
{
if (!AssetUpdateManager.useResources)
AssetManager.instance.bundleManager.downloadHub.StartBackGroundDownload();
}
2024-08-23 15:49:34 +08:00
public static void CreateInstance()
{
var loadObject = new GameObject("LoadAssetBundle");
loadObject.AddComponent<LoadAssetBundle>();
}
public void ClearCallbacks()
{
_gameObjectList.Clear();
_assetList.Clear();
_audioList.Clear();
_textAssetList.Clear();
_spriteList.Clear();
_rawImageList.Clear();
}
private bool IsBundleAndAssetValid(string bundleName, string assetName)
{
return !string.IsNullOrEmpty(bundleName) &&
!string.IsNullOrEmpty(assetName) &&
!bundleName.Equals("-1") &&
2024-08-23 15:49:34 +08:00
!assetName.Equals("-1");
}
private void LoadAssetFromList<T>(string bundleName, string assetName, LoadBundleAssetCallback<T> callback,
Hashtable hashtable, LoadAssetRequestList<T> list, bool archive) where T : Object
2024-08-23 15:49:34 +08:00
{
// 已知问题,即使已经加载的资源,仍然会产生一次列表推入和回调监听,造成少量性能浪费
// 暂时不修改这个结构,保持当前强健的逻辑流程
list.AddCallback(bundleName, assetName, callback, hashtable);
LoadAssetInternal<T>(bundleName, assetName);
}
2024-08-23 15:49:34 +08:00
private void RemoveAllCallback(string bundleName, string assetName)
{
_gameObjectList.RemoveAllCallback(bundleName, assetName);
_assetList.RemoveAllCallback(bundleName, assetName);
_audioList.RemoveAllCallback(bundleName, assetName);
_textAssetList.RemoveAllCallback(bundleName, assetName);
_spriteList.RemoveAllCallback(bundleName, assetName);
_rawImageList.RemoveAllCallback(bundleName, assetName);
}
public void LoadGameObject(string bundleName, string assetName, LoadBundleAssetCallback<GameObject> callback,
Hashtable hashParam, bool archive = false)
2024-08-23 15:49:34 +08:00
{
if (IsBundleAndAssetValid(bundleName, assetName))
{
bundleName += assetName;
bundleName = FixBundleName(bundleName);
2024-08-23 15:49:34 +08:00
LoadAssetFromList(bundleName, assetName, callback, hashParam, _gameObjectList, archive);
}
}
public void LoadAsset(string bundleName, string assetName, LoadBundleAssetCallback<Object> callback,
Hashtable hashParam, bool archive = false)
2024-08-23 15:49:34 +08:00
{
if (IsBundleAndAssetValid(bundleName, assetName))
{
bundleName = FixBundleName(bundleName);
LoadAssetFromList(bundleName, assetName, callback, hashParam, _assetList, archive);
}
}
public void RemoveAssetCallback(string bundleName, string assetName, LoadBundleAssetCallback<Object> callback)
{
if (IsBundleAndAssetValid(bundleName, assetName))
{
bundleName = FixBundleName(bundleName);
_assetList.RemoveCallback(bundleName, assetName, callback);
}
}
/// <summary>
/// GameObject加载需求的析构接口因为会修改AssetBundle名称使用一个统一接口
/// </summary>
public void UnloadAssetWithPathFix(string bundleName, string assetName)
{
if (!AssetUpdateManager.useResources && IsBundleAndAssetValid(bundleName, assetName))
{
bundleName = bundleName + assetName;
bundleName = FixBundleName(bundleName);
RemoveAllCallback(bundleName, assetName);
AssetManager.instance.RemoveAsset(bundleName, assetName);
}
}
/// <summary>
/// GameObject加载需求的析构接口不会修改bundleName因此不要给会用资源名校正包名资源的使用
/// </summary>
public void UnloadAsset(string bundleName, string assetName)
{
if (!AssetUpdateManager.useResources && IsBundleAndAssetValid(bundleName, assetName))
{
bundleName = FixBundleName(bundleName);
RemoveAllCallback(bundleName, assetName);
AssetManager.instance.RemoveAsset(bundleName, assetName);
}
}
public void LoadUI(string bundleName, string assetName, LoadBundleAssetCallback<GameObject> callback,
Hashtable hashParam, bool archive = true)
2024-08-23 15:49:34 +08:00
{
if (IsBundleAndAssetValid(bundleName, assetName))
{
bundleName = FixBundleName(bundleName);
LoadAssetFromList(bundleName, assetName, callback, hashParam, _gameObjectList, archive);
}
}
public void LoadSoundAsync(string bundlePath, string assetName, LoadBundleAssetCallback<AudioClip> callback,
Hashtable hashParam)
2024-08-23 15:49:34 +08:00
{
if (!string.IsNullOrEmpty(assetName))
if (IsBundleAndAssetValid(bundlePath, assetName))
{
bundlePath = FixBundleName(bundlePath);
LoadAssetFromList(bundlePath, assetName, callback, hashParam, _audioList, true);
}
}
public void SetRawTexture(RawImage image, string assetName, string bundleName)
{
var valid = false;
if (image != null)
{
if (image.texture == null)
{
image.enabled = false;
valid = true;
2024-08-23 15:49:34 +08:00
}
else
{
valid = !image.texture.name.Equals(assetName);
}
}
if (valid && IsBundleAndAssetValid(bundleName, assetName))
{
bundleName = FixBundleName(bundleName);
_rawImageList.AddCallback(bundleName, assetName, image);
LoadAssetInternal<Texture>(bundleName, assetName);
}
}
public void SetImageSprite(Image image, string assetName, LoadSpritesCallback callback = null)
{
var valid = false;
if (image != null)
{
if (image.sprite == null)
{
image.enabled = false;
valid = true;
2024-08-23 15:49:34 +08:00
}
else
{
valid = !image.sprite.name.Equals(assetName);
}
}
2024-08-23 15:49:34 +08:00
if (valid && IsBundleAndAssetValid(BUNDLE_PATH_SPRITE, assetName))
{
// 试图校正精灵包名
var bundleName = GetAtlasBundleName(BUNDLE_PATH_SPRITE, assetName);
_spriteList.AddCallback(bundleName, assetName, image, callback);
LoadAssetInternal<Sprite>(bundleName, assetName);
}
}
/// <summary>
/// 统一使用一个接口来处理修复Bundle名称之类的问题
/// </summary>
private void LoadAssetInternal<T>(string bundleName, string assetName) where T : Object
{
#if UNITY_EDITOR
if (AssetUpdateManager.useResources)
LoadForSimulateMode(bundleName, assetName, typeof(T));
else
#endif
AssetManager.instance.LoadAsset<T>(bundleName, assetName, this, OnAssetLoadedFinish);
}
2024-08-23 15:49:34 +08:00
private void OnAssetLoadedFinish<T>(string bundleName, string assetName, T asset) where T : Object
{
_gameObjectList.FinishAsset(bundleName, assetName, asset);
_assetList.FinishAsset(bundleName, assetName, asset);
_audioList.FinishAsset(bundleName, assetName, asset);
_textAssetList.FinishAsset(bundleName, assetName, asset);
_spriteList.FinishAsset(bundleName, assetName, asset);
_rawImageList.FinishAsset(bundleName, assetName, asset);
}
2024-08-23 15:49:34 +08:00
#if UNITY_EDITOR
[Serializable]
public class EditorBundleList
{
private readonly Dictionary<string, string> _assetDataList = new Dictionary<string, string>();
2024-08-23 15:49:34 +08:00
public EditorBundleList(IEnumerable<string> assets)
{
foreach (var asset in assets)
{
_assetDataList[Path.GetFileName(asset).ToLower()] = asset;
}
}
public string GetAssetPath(string assetName)
{
string result;
if (!_assetDataList.TryGetValue(assetName, out result))
result = string.Empty;
return result;
}
}
private class EditorResourceAsync
{
public readonly string bundleName;
public readonly string assetName;
2024-08-23 15:49:34 +08:00
public readonly AsyncOperation operation;
2024-08-23 15:49:34 +08:00
public EditorResourceAsync(string bundleName, string assetName, AsyncOperation operation)
{
this.bundleName = bundleName;
this.assetName = assetName;
this.operation = operation;
2024-08-23 15:49:34 +08:00
}
}
2024-08-23 15:49:34 +08:00
public const string assetPathHeader = "Assets/Project3D/Resources";
public const string uiSpriteAssetPath = "Assets/Project3D/Sprites";
public const string bundleToAssetPath = "Assets/Editor/Config/BundleToAsset" + AssetConst.bytesExtension;
private Dictionary<string, string> _uiCommonPathDict;
private Dictionary<string, EditorBundleList> _resourcesDict;
2024-08-23 15:49:34 +08:00
private const int _maxAsyncCount = 1;
private readonly List<EditorResourceAsync> _asyncList = new List<EditorResourceAsync>();
private readonly Queue<MyTuple<string, string>> _pendingList = new Queue<MyTuple<string, string>>();
2024-08-23 15:49:34 +08:00
private void OnResourcesLoad(AsyncOperation operation)
{
var resourceRequest = operation as ResourceRequest;
if (resourceRequest != null)
{
for (var i = _asyncList.Count - 1; i >= 0; i--)
{
var async = _asyncList[i];
if (async.operation == operation)
{
_asyncList.RemoveAt(i);
OnAssetLoadedFinish(async.bundleName, async.assetName, resourceRequest.asset);
}
}
2024-08-23 15:49:34 +08:00
while (_asyncList.Count < _maxAsyncCount && _pendingList.Count > 0)
{
var task = _pendingList.Dequeue();
StartResourceLoad(task.first, task.second);
}
}
}
private void StartResourceLoad(string bundleName, string assetName)
{
if (_resourcesDict == null)
{
var dataPath = Application.dataPath.MoveUp().Open(bundleToAssetPath);
if (File.Exists(dataPath))
{
var bitFormatter = new BinaryFormatter();
using (var fs = File.OpenRead(dataPath))
_resourcesDict = bitFormatter.Deserialize(fs) as Dictionary<string, EditorBundleList>;
}
2024-08-23 15:49:34 +08:00
if (_resourcesDict == null)
_resourcesDict = new Dictionary<string, EditorBundleList>();
}
EditorBundleList list;
if (!_resourcesDict.TryGetValue(bundleName, out list))
{
var assets = AssetDatabase.GetAssetPathsFromAssetBundle(bundleName + AssetConst.bundleVariant)
.Where(a => a.StartsWith(assetPathHeader))
.Select(a => a.RemoveExtension().Substring(assetPathHeader.Length + 1)).ToArray();
2024-08-23 15:49:34 +08:00
if (assets.Length > 0)
{
list = new EditorBundleList(assets);
2024-08-23 15:49:34 +08:00
_resourcesDict[bundleName] = list;
var bitFormatter = new BinaryFormatter();
var dataPath = Application.dataPath.MoveUp().Open(bundleToAssetPath);
2024-08-23 15:49:34 +08:00
using (var fs = File.OpenWrite(dataPath))
bitFormatter.Serialize(fs, _resourcesDict);
}
}
2024-08-23 15:49:34 +08:00
var path = list != null
? list.GetAssetPath(assetName.ToLower())
: string.Empty;
if (string.IsNullOrEmpty(path))
{
Debug.LogError(string.Format("Unable to load asset {0} from bundle {1}!", assetName, bundleName));
// ReSharper disable once ExpressionIsAlwaysNull
OnAssetLoadedFinish(bundleName, assetName, default(Object));
}
else
{
var request = Resources.LoadAsync(path);
_asyncList.Add(new EditorResourceAsync(bundleName, assetName, request));
request.completed += OnResourcesLoad;
}
}
2024-08-23 15:49:34 +08:00
private void LoadForSimulateMode(string bundleName, string assetName, Type assetType)
{
Object asset = null;
// 2019.03.01 不再试图维护Simulate的流程uiCommonSprite直接走内置流程。
if (bundleName.StartsWith("ui/sprite/"))
{
if (_uiCommonPathDict == null)
{
_uiCommonPathDict = new Dictionary<string, string>();
var uiCommonPaths = from assetPath in AssetDatabase.GetAllAssetPaths()
where assetPath.StartsWith(uiSpriteAssetPath)
where !string.IsNullOrEmpty(Path.GetExtension(assetPath))
select assetPath;
foreach (var uiPath in uiCommonPaths)
{
var key = Path.GetFileNameWithoutExtension(uiPath).ToLower();
if (_uiCommonPathDict.ContainsKey(key))
Debug.LogError("Duplicate Key Found for " + uiPath + " and " + _uiCommonPathDict[key]);
else
_uiCommonPathDict.Add(key, uiPath);
}
}
string path;
if (_uiCommonPathDict.TryGetValue(assetName.ToLower(), out path))
asset = AssetDatabase.LoadAssetAtPath(path, assetType);
else
Debug.LogError("No Path for item " + assetName.ToLower());
OnAssetLoadedFinish(bundleName, assetName, asset);
}
else
{
var callBack = _asyncList.Find(a => a.bundleName == bundleName && a.assetName == assetName);
if (callBack == null)
{
if (_asyncList.Count < _maxAsyncCount)
StartResourceLoad(bundleName, assetName);
else
_pendingList.Enqueue(new MyTuple<string, string>(bundleName, assetName));
}
}
}
#endif
#endregion
#region load init
public static LoadAssetBundle Instance { get; private set; }
2024-08-23 15:49:34 +08:00
// public void UnloadBundle(string bundleName)
// {
// Debug.Log("Unload Bundle: " + bundleName);
// if (!AssetUpdateManager.useResources)
// {
// bundleName = FixBundleName(bundleName);
// AssetManager.instance.RemovePreload(bundleName);
// }
// }
/// <summary>
/// 统一处理一些AssetBundle后缀名称问题
/// </summary>
public static string FixBundleName(string bundleName)
{
// var extension = Path.GetExtension();
// if (string.IsNullOrEmpty(extension))
// {
// bundleName += bundleFileExtension;
// }
// else if (!extension.Equals(bundleFileExtension, StringComparison.CurrentCultureIgnoreCase))
// {
// bundleName = bundleName.Remove(bundleName.Length - extension.Length);
// bundleName += bundleFileExtension;
// }
return bundleName.RemoveExtension().ToLower();
}
2024-08-23 15:49:34 +08:00
// /// <summary>
// /// 加载一个AssetBundle如果Bundle已经加载就返回true
// /// </summary>
// private void LoadOneAssetBundle(string bundleName)
// {
// bundleName = FixBundleName(bundleName);
// AssetManager.instance.Preload(bundleName, this, OnAssetBundleLoaded);
// }
2024-08-23 15:49:34 +08:00
#endregion
#region
/// <summary>
/// 预加载场景电影Bundle
/// </summary>
private readonly List<int> _movieId = new List<int>();
2024-08-23 15:49:34 +08:00
private string _preloadScene;
private static string GetMovieName(int movieId)
{
var movieName = string.Empty;
if (movieId >= 0)
{
var movieData = TableManager.GetSceneMovieByID(movieId);
if (movieData != null)
{
var profession = GameManager.gameManager.PlayerDataPool.MainPlayerBaseAttr.Profession;
movieName = movieData.GetResPathbyIndex(profession);
}
}
2024-08-23 15:49:34 +08:00
return movieName;
}
private void AddMoviePreload(int movieId)
{
var movieName = GetMovieName(movieId);
if (!string.IsNullOrEmpty(movieName))
Instance.LoadGameObject(BUNDLE_PATH_MODEL, movieName, null, null);
}
2024-08-23 15:49:34 +08:00
private void RemoveMoviePreload(int movieId)
{
var movieName = GetMovieName(movieId);
if (!string.IsNullOrEmpty(movieName))
{
var bundleName = BUNDLE_PATH_MODEL + movieName;
bundleName = FixBundleName(bundleName);
Instance.UnloadAsset(bundleName, movieName);
}
}
2024-08-23 15:49:34 +08:00
public void StartPreloadScene(string sceneName, int movieId)
{
#if UNITY_EDITOR
if (AssetUpdateManager.useResources)
return;
#endif
sceneName = GetSceneBundleName(sceneName);
// 如果场景对不上,则卸载之前的场景预加载
var loadScene = _preloadScene != sceneName;
if (loadScene)
{
if (!string.IsNullOrEmpty(_preloadScene))
CleanPreloadScene();
_preloadScene = sceneName;
}
2024-08-23 15:49:34 +08:00
if (!_movieId.Contains(movieId))
AddMoviePreload(movieId);
}
public void CleanPreloadScene()
{
_preloadScene = string.Empty;
foreach (var id in _movieId)
RemoveMoviePreload(id);
_movieId.Clear();
}
2024-08-23 15:49:34 +08:00
#endregion
2024-08-23 15:49:34 +08:00
#region loadScene
2024-08-23 15:49:34 +08:00
/// <summary>
/// 是否允许加载场景
/// </summary>
// 注如果当前有其他SceneLoadOperaction则不允许继续加载场景
public bool AllowLoadScene()
{
return !AssetManager.instance.IsLoadingScene();
}
2024-08-23 15:49:34 +08:00
public static string GetSceneBundleName(string sceneName)
{
var bundleName = "scene/" + sceneName;
bundleName = FixBundleName(bundleName);
return bundleName;
}
public void UnloadMainScene()
{
if (!AssetUpdateManager.useResources)
AssetManager.instance.UnloadAllScene();
}
2024-08-23 15:49:34 +08:00
/// <summary>
/// 加载主要场景 - 主要场景加载时,会卸载之前的主要场景
/// </summary>
public bool LoadMainScene(string assetName, LoadSceneMode mode, out SceneHandle loadHandle)
{
bool load;
if (AssetUpdateManager.useResources)
{
load = true;
2024-08-23 15:49:34 +08:00
loadHandle = null;
SceneManager.LoadScene(assetName);
}
else
{
var bundleName = GetSceneBundleName(assetName);
var current = AssetManager.instance.GetCurrentSceneHandle();
2024-08-23 15:49:34 +08:00
load = current == null || current.sceneName == assetName;
if (!load)
load = AllowLoadScene();
loadHandle = load ? AssetManager.instance.LoadScene(bundleName, assetName, mode, allowReload: true) : null;
}
2024-08-23 15:49:34 +08:00
return load;
}
2024-08-23 15:49:34 +08:00
#endregion
#region loadGameRes
public static string gameResBundleName
{
get { return FixBundleName(BUNDLE_PATH_GAMERES); }
}
2024-08-23 15:49:34 +08:00
#endregion
#region LoadTable
private const string _tableBundleName = "tables";
public TextAsset LoadTableAsset(string tableName)
{
return LoadTextAsset(_tableBundleName, tableName);
}
#if UNITY_EDITOR
public const string tablePath = "Assets/Project3D/BundleData/Tables3D/";
private Dictionary<string, string> _luaFiles;
2024-08-23 15:49:34 +08:00
#endif
private TextAsset LoadTextAsset(string bundleName, string assetName)
{
TextAsset result = null;
#if UNITY_EDITOR
if (AssetUpdateManager.useResources)
{
if (bundleName == _scriptBundleName)
{
if (_luaFiles == null)
{
_luaFiles = new Dictionary<string, string>();
var luaPath = "Assets".Open("Project").Open("Script").Open("LuaScripts") + '/';
var scripts = AssetDatabase.GetAllAssetPaths().Where(a => a.StartsWith(luaPath))
.Where(a => AssetConst.textExtension.Equals(Path.GetExtension(a)));
2024-08-23 15:49:34 +08:00
foreach (var script in scripts)
_luaFiles.Add(Path.GetFileNameWithoutExtension(script).ToLower(), script);
}
2024-08-23 15:49:34 +08:00
string path;
if (_luaFiles.TryGetValue(assetName.ToLower(), out path))
result = AssetDatabase.LoadAssetAtPath<TextAsset>(path);
}
else if (bundleName == _tableBundleName)
{
var extension = string.Equals(assetName, atlasPathConvertTable, StringComparison.Ordinal)
? AssetConst.bytesExtension
: AssetConst.textExtension;
result = AssetDatabase.LoadAssetAtPath<TextAsset>(tablePath + assetName + extension);
}
else
Debug.LogError(string.Format("Unable to load TextAsset {1} from bundle {0}!", bundleName, assetName));
2024-08-23 15:49:34 +08:00
return result;
}
#endif
if (AssetManager.instance == null)
{
throw new Exception("AssetManager is not initialized!");
}
2024-08-23 15:49:34 +08:00
result = AssetManager.instance.LoadAssetSync<TextAsset>(bundleName, assetName);
return result;
}
#endregion
2024-08-23 15:49:34 +08:00
#region LoadScript
// 注之前逻辑是和LoadTable在一起但是没有监听过这个AssetBundle是否加载结束的
// 暂时保持接口和调用处不变
private const string _scriptBundleName = "script";
public TextAsset LoadScriptAsset(string script)
{
return LoadTextAsset(_scriptBundleName, script);
}
#endregion
2024-08-23 15:49:34 +08:00
#region Atlas Path Convert
private Dictionary<string, string> _pathConvertDict;
2024-08-23 15:49:34 +08:00
private void CreateAtlasConvert()
{
_pathConvertDict = new Dictionary<string, string>();
var lines = AssetUtils.TextToLines(LoadTableAsset(atlasPathConvertTable).text);
foreach (var line in lines)
{
if (!string.IsNullOrEmpty(line))
{
var keyValue = line.Split('\t');
_pathConvertDict[keyValue[0]] = keyValue[1];
}
}
}
private string GetAtlasBundleName(string bundleName, string assetName)
{
if (_pathConvertDict == null)
CreateAtlasConvert();
string newName;
if (_pathConvertDict.TryGetValue(assetName.ToLower(), out newName))
bundleName = newName;
else
{
LogModule.ErrorLog(string.Format(
"Try to load asset {0} from {1}, while Asset Load Manager hasn't init path conversion yet!",
assetName, bundleName));
2024-08-23 15:49:34 +08:00
}
2024-08-23 15:49:34 +08:00
return bundleName;
}
2024-08-23 15:49:34 +08:00
#endregion
}
#region Load Asset Data
public delegate void LoadSpritesCallback(bool isSucess, GameObject obj);
public delegate void LoadBundleAssetCallback<in T>(string assetName, T assetItem, Hashtable hashTable) where T : Object;
public delegate void LoadAssetBundleFinish(string bundleName);
public abstract class LoadAssetRequestBase
{
public readonly string assetName;
public readonly string bundleName;
protected LoadAssetRequestBase(string bundleName, string assetName)
{
this.bundleName = bundleName;
this.assetName = assetName;
2024-08-23 15:49:34 +08:00
}
}
public static class LoadAssetRequestMethods
{
public static int GetIndexFromList<T>(this List<T> requestList, string bundleName, string assetName)
where T : LoadAssetRequestBase
{
var result = -1;
for (var i = 0; i < requestList.Count; i++)
if (requestList[i].bundleName.Equals(bundleName, StringComparison.OrdinalIgnoreCase) &&
requestList[i].assetName.Equals(assetName, StringComparison.Ordinal))
{
result = i;
break;
}
return result;
}
}
public class LoadRawImageRequest : LoadAssetRequestBase
{
public readonly List<RawImage> rawImageList = new List<RawImage>();
public LoadRawImageRequest(string bundleName, string assetName) : base(bundleName, assetName)
{
}
public void AddCallback(RawImage rawImage)
{
if (!rawImageList.Contains(rawImage))
rawImageList.Add(rawImage);
}
public void RemoveCallback(RawImage rawImage)
{
rawImageList.Remove(rawImage);
}
public void FinishAsset(Object asset)
{
var texture = asset as Texture;
for (var i = 0; i < rawImageList.Count; i++)
if (rawImageList[i])
{
rawImageList[i].texture = texture;
rawImageList[i].enabled = true;
}
}
}
public class LoadSpriteRequest : LoadAssetRequestBase
{
public readonly List<MyTuple<Image, LoadSpritesCallback>> callBackList =
new List<MyTuple<Image, LoadSpritesCallback>>();
public LoadSpriteRequest(string bundleName, string assetName) : base(bundleName, assetName)
{
}
public void AddCallback(Image image, LoadSpritesCallback callback)
{
var index = GetCallBackIndex(image);
if (index >= 0)
callBackList[index].second = callback;
else
callBackList.Add(new MyTuple<Image, LoadSpritesCallback>(image, callback));
}
public void RemoveCallback(Image image)
{
var index = GetCallBackIndex(image);
if (index >= 0)
callBackList.RemoveAt(index);
}
private int GetCallBackIndex(Image image)
{
var result = -1;
for (var i = 0; i < callBackList.Count; i++)
if (callBackList[i].first == image)
{
result = i;
break;
}
return result;
}
public void FinishAsset(Object asset)
{
var sprite = asset as Sprite;
for (var i = 0; i < callBackList.Count; i++)
if (callBackList[i].first)
{
callBackList[i].first.sprite = sprite;
2024-08-23 15:49:34 +08:00
callBackList[i].first.enabled = true;
if (callBackList[i].second != null)
callBackList[i].second.Invoke(true, callBackList[i].first.gameObject);
}
}
}
public class LoadAssetRequest<T> : LoadAssetRequestBase where T : Object
{
public readonly List<MyTuple<LoadBundleAssetCallback<T>, Hashtable>> callBackList =
new List<MyTuple<LoadBundleAssetCallback<T>, Hashtable>>();
public LoadAssetRequest(string bundleName, string assetName) : base(bundleName, assetName)
{
}
public void AddCallback(LoadBundleAssetCallback<T> callback, Hashtable hashTable)
{
var index = GetCallbackIndex(callback);
if (index < 0)
callBackList.Add(new MyTuple<LoadBundleAssetCallback<T>, Hashtable>(callback, hashTable));
else
callBackList[index].second = hashTable;
}
public void RemoveCallback(LoadBundleAssetCallback<T> callback)
{
var index = GetCallbackIndex(callback);
if (index >= 0)
callBackList.RemoveAt(index);
}
private int GetCallbackIndex(LoadBundleAssetCallback<T> callback)
{
var result = -1;
for (var i = 0; i < callBackList.Count; i++)
if (callBackList[i].first == callback)
{
result = i;
break;
}
return result;
}
public void FinishAsset(Object asset)
{
var item = asset as T;
for (var i = 0; i < callBackList.Count; i++)
if (callBackList[i].first != null)
callBackList[i].first.Invoke(assetName, item, callBackList[i].second);
}
}
public class LoadRawImageRequestList
{
private readonly List<LoadRawImageRequest> _callbackList = new List<LoadRawImageRequest>();
public void AddCallback(string bundleName, string assetName, RawImage rawImage)
{
var index = _callbackList.GetIndexFromList(bundleName, assetName);
2024-08-23 15:49:34 +08:00
LoadRawImageRequest request;
if (index < 0)
{
request = new LoadRawImageRequest(bundleName, assetName);
_callbackList.Add(request);
}
else
{
request = _callbackList[index];
}
request.AddCallback(rawImage);
}
public void RemoveCallback(string bundleName, string assetName, RawImage rawImage)
{
var index = _callbackList.GetIndexFromList(bundleName, assetName);
if (index >= 0)
{
_callbackList[index].RemoveCallback(rawImage);
if (_callbackList[index].rawImageList.Count <= 0)
_callbackList.RemoveAt(index);
}
}
public void RemoveAllCallback(string bundleName, string assetName)
{
var index = _callbackList.GetIndexFromList(bundleName, assetName);
if (index >= 0)
_callbackList.RemoveAt(index);
}
public void FinishAsset(string bundleName, string assetName, Object asset)
{
// 这个接收底层回调的消息,不会出现名字错误的问题
var index = _callbackList.GetIndexFromList(bundleName, assetName);
if (index >= 0)
{
var item = _callbackList[index];
_callbackList.RemoveAt(index);
item.FinishAsset(asset);
}
}
2024-08-23 15:49:34 +08:00
public void Clear()
{
_callbackList.Clear();
}
}
public class LoadSpriteRequestList
{
private readonly List<LoadSpriteRequest> _callbackList = new List<LoadSpriteRequest>();
public void AddCallback(string bundleName, string assetName, Image image, LoadSpritesCallback callback)
{
bundleName = LoadAssetBundle.FixBundleName(bundleName);
var index = _callbackList.GetIndexFromList(bundleName, assetName);
2024-08-23 15:49:34 +08:00
LoadSpriteRequest request;
if (index < 0)
{
request = new LoadSpriteRequest(bundleName, assetName);
_callbackList.Add(request);
}
else
{
request = _callbackList[index];
}
request.AddCallback(image, callback);
}
public void RemoveCallback(string bundleName, string assetName, Image image)
{
bundleName = LoadAssetBundle.FixBundleName(bundleName);
var index = _callbackList.GetIndexFromList(bundleName, assetName);
if (index >= 0)
{
_callbackList[index].RemoveCallback(image);
if (_callbackList[index].callBackList.Count <= 0)
_callbackList.RemoveAt(index);
}
}
public void RemoveAllCallback(string bundleName, string assetName)
{
bundleName = LoadAssetBundle.FixBundleName(bundleName);
var index = _callbackList.GetIndexFromList(bundleName, assetName);
if (index >= 0)
_callbackList.RemoveAt(index);
}
public void FinishAsset(string bundleName, string assetName, Object asset)
{
// 这个接收底层回调的消息,不会出现名字错误的问题
var index = _callbackList.GetIndexFromList(bundleName, assetName);
if (index >= 0)
{
var item = _callbackList[index];
_callbackList.RemoveAt(index);
item.FinishAsset(asset);
}
}
public void Clear()
{
_callbackList.Clear();
}
}
public class LoadAssetRequestList<T> where T : Object
{
private readonly List<LoadAssetRequest<T>> _callbackList = new List<LoadAssetRequest<T>>();
public void AddCallback(string bundleName, string assetName, LoadBundleAssetCallback<T> callback,
Hashtable hashTable)
2024-08-23 15:49:34 +08:00
{
var index = _callbackList.GetIndexFromList(bundleName, assetName);
2024-08-23 15:49:34 +08:00
LoadAssetRequest<T> request;
if (index < 0)
{
request = new LoadAssetRequest<T>(bundleName, assetName);
_callbackList.Add(request);
}
else
{
request = _callbackList[index];
}
request.AddCallback(callback, hashTable);
}
public void RemoveCallback(string bundleName, string assetName, LoadBundleAssetCallback<T> callback)
{
var index = _callbackList.GetIndexFromList(bundleName, assetName);
if (index >= 0)
{
_callbackList[index].RemoveCallback(callback);
if (_callbackList[index].callBackList.Count <= 0)
_callbackList.RemoveAt(index);
}
}
public void RemoveAllCallback(string bundleName, string assetName)
{
var index = _callbackList.GetIndexFromList(bundleName, assetName);
if (index >= 0)
_callbackList.RemoveAt(index);
}
public void FinishAsset(string bundleName, string assetName, Object asset)
{
// 这个接收底层回调的消息,不会出现名字错误的问题
var index = _callbackList.GetIndexFromList(bundleName, assetName);
if (index >= 0)
{
var item = _callbackList[index];
_callbackList.RemoveAt(index);
item.FinishAsset(asset);
}
}
public void Clear()
{
_callbackList.Clear();
}
}
/// <summary>
/// 部分系统会需要穿越Asset级别直接操作AssetBundle保留这么一个回调
/// </summary>
public class LoadWholeBundleRequest
{
public readonly List<LoadAssetBundleFinish> callbackList = new List<LoadAssetBundleFinish>();
public readonly string name;
2024-08-23 15:49:34 +08:00
public LoadWholeBundleRequest(string bundleName)
{
name = bundleName;
}
public void AddCallback(LoadAssetBundleFinish callback)
{
if (!callbackList.Contains(callback))
callbackList.Add(callback);
}
public void RemoveCallback(LoadAssetBundleFinish callback)
{
callbackList.Remove(callback);
}
public void FinishAssetBundleLoad()
{
for (var i = 0; i < callbackList.Count; i++)
try
{
if (callbackList[i] != null)
callbackList[i].Invoke(name);
}
catch (Exception e)
{
LogModule.ErrorLog(e.ToString());
}
}
}
// public class LoadWholeBundleList
// {
// private readonly List<LoadWholeBundleRequest> _callbackList = new List<LoadWholeBundleRequest>();
//
// public void AddCallback(string bundleName, LoadAssetBundleFinish callback)
// {
// var index = GetCallbackIndex(bundleName);
// LoadWholeBundleRequest request;
// if (index < 0)
// {
// request = new LoadWholeBundleRequest(bundleName);
// _callbackList.Add(request);
// }
// else
// {
// request = _callbackList[index];
// }
//
// request.AddCallback(callback);
// }
//
// public void RemoveCallback(string bundleName, LoadAssetBundleFinish callback)
// {
// var index = GetCallbackIndex(bundleName);
// if (index >= 0)
// {
// _callbackList[index].RemoveCallback(callback);
// if (_callbackList[index].callbackList.Count <= 0)
// _callbackList.RemoveAt(index);
// }
// }
//
// public void FinishBundle(string bundleName)
// {
// var index = GetCallbackIndex(bundleName);
// if (index >= 0)
// {
// var item = _callbackList[index];
// _callbackList.RemoveAt(index);
// item.FinishAssetBundleLoad();
// }
// }
//
// private int GetCallbackIndex(string bundleName)
// {
// var index = -1;
// for (var i = 0; i < _callbackList.Count; i++)
// if (_callbackList[i].name.Equals(bundleName, StringComparison.OrdinalIgnoreCase))
// {
// index = i;
// break;
// }
//
// return index;
// }
//
// public void Clear()
// {
// _callbackList.Clear();
// }
// }
#endregion