这个assetbundle loader脚本会不会是我的游戏内存泄漏问题的根源?缓存 AssetBundle 对象不好吗?
public class AssetLoadWrapper{
public static Dictionary<string, AssetBundle> cacheBundle;
public static HashSet<string> assetLock;
public static IEnumerator loadAsset<T> (string path, System.Action<T> onFinished, bool isAssetBundle = false) where T:UnityEngine.Object {
//doing locking mechanism if one want to access currently the same asset
if (assetLock == null)
assetLock = new HashSet<string> ();
while (assetLock.Contains (path)) {
yield return 0;
}
assetLock.Add (path);
//check if the path pointing to assetbundle or just loading to Resource folder
if (isAssetBundle) {
//cache initialization
if (cacheBundle == null) {
cacheBundle = new Dictionary<string, AssetBundle> ();
}
//check if assetbundle already in the cache, if yes, then just load the main asset from the cache
if (cacheBundle.ContainsKey (DataManager.GetCachePathForAsset () + "/assets/" + path + ".unity3d") && cacheBundle [GaritaDataManager.CachePathForGarita () + "/assets/" + path + ".unity3d"] != null) {
AssetBundle temp = cacheBundle [DataManager.GetCachePathForAsset () + "/assets/" + path + ".unity3d"];
//the main asset is the one what I want to load in game scene
T tempData = temp.mainAsset as T;
temp.Unload (false);
//return the asset via callback
if (onFinished != null)
onFinished (tempData);
}
// if the assetbundle is not in the cache
else {
//check if the assetbundle .unity3d exists on the local disk
bool exists = System.IO.File.Exists (DataManager.GetCachePathForAsset () + "/assets/" + path + ".unity3d");
byte[] bytes = null;
if (exists)
bytes = System.IO.File.ReadAllBytes (DataManager.GetCachePathForAsset () + "/assets/" + path + ".unity3d");
//if not exist, then just callback with the null data
if (bytes == null) {
onFinished (null);
LogUtil.Error ("LoadAsset", "bytes = null => " + DataManager.GetCachePathForAsset () + "/assets/" + path + ".unity3d");
//remove the lock
assetLock.Remove (path);
yield break;
}
//create assetbundle from the memory
AssetBundleCreateRequest www = AssetBundle.CreateFromMemory (bytes);
www.priority = int.MaxValue;
while (!www.isDone) {
yield return 0;
}
//if it is valid assetbundle
if (www.assetBundle != null) {
T data = www.assetBundle.mainAsset as T;
//cache the main asset to the cache
if (!cacheBundle.ContainsKey (DataManager.GetCachePathForAsset () + "/assets/" + path + ".unity3d"))
cacheBundle.Add (DataManager.GetCachePathForAsset () + "/assets/" + path + ".unity3d", www.assetBundle);
else
cacheBundle [DataManager.GetCachePathForAsset () + "/assets/" + path + ".unity3d"] = www.assetBundle;
//since i just need the main asset, i dont need another asset, i just pass "false" to assetbundle.unload method
//and the responsibility if the main asset is needed or not, is passed on to the one who needs this asset.
// i am assumming that if i dont needed the asset anymore, i just set the reference to the assetbundle data to
// null, and calling Resources.UnloadUnusedAsset() respectively in order to free the memory
www.assetBundle.Unload (false);
if (onFinished != null)
onFinished (data);
} else {
LogUtil.Error ("LoadAsset", "www.assetBundle = null => " + DataManager.GetCachePathForAsset () + "/assets/" + path + ".unity3d");
if (onFinished != null)
onFinished (null);
}
}
} else {
Object t = Resources.Load (path);
if (onFinished != null)
onFinished (t as T);
}
assetLock.Remove (path);
}