0

这个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);
}
4

1 回答 1

0

我看到您已卸载“未使用”资产但未使用资产。当您使用完资产包中的资产后,您必须使用“true”标志卸载资产包。这记录在这里: http ://docs.unity3d.com/ScriptReference/AssetBundle.Unload.html

于 2015-08-21T22:17:19.460 回答