首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >内存泄漏的来源来自我的Unity3d资产捆绑加载器脚本?

内存泄漏的来源来自我的Unity3d资产捆绑加载器脚本?
EN

Stack Overflow用户
提问于 2014-01-22 11:25:10
回答 1查看 2K关注 0票数 0

这个assetbundle加载器脚本会不会是我的游戏内存泄漏问题的根源?缓存AssetBundle-object是不好的吗?

代码语言:javascript
复制
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);
}
EN

回答 1

Stack Overflow用户

发布于 2015-08-22 06:17:19

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21273588

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档