iOS上的AssetBundles:内存总是增加,导致崩溃

时间:2014-03-28 21:37:52

标签: unity3d assetbundle

我们将资产包存储在Amazon S3存储桶中。当游戏开始时,它使用WWW.LoadFromCacheOrDownload确定下载新版本所需的捆绑包。

我们遇到的问题是它为我们的应用程序分配的内存iOS报告不断增加,但Unity报告它使用(通过探查器)的内存始终保持不变。我们有足够的捆绑包,当它完成我们需要的所有内容的下载时,它总是收到来自iOS的内存警告,并且由于内存压力很快就会关闭。

我们现有的常用解决方案:在WWW完成后卸载assetbundle,使用assetBundle.unload(),调用Resources.UnloadUnusedAssets(),并在WWW上调用Dispose()。这些都没有解决问题。

代码如下:

    private IEnumerator DownloadBundle(DownloadQueueEntry entry, DownloadFinishedCallback callback)
    {
        while (!entry.finished)
        {
            // grab bundle off S3
            string url = string.Format(BUNDLE_URL_FORMAT, entry.directory, entry.assetName);

            WWW www = WWW.LoadFromCacheOrDownload(url, entry.version);

            yield return www;

            if (string.IsNullOrEmpty(www.error))
            {
                Debug.Log("[BundleDownloader] Download Completed " + entry.assetName);

                entry.finished = true;
                entry.downloading = false;
                www.assetBundle.Unload (true);
                Resources.UnloadUnusedAssets ();
            }
            else
            {
                // usually timed out resolving host, just try again for now
                Debug.LogError("[BundleDownloader] Download failed: " + url + " Error: " + www.error);
            }

            www.Dispose();
            www = null;
        }
        if(callback != null)
        {
            callback ();
        }

    }

- 编辑 -

显示内存使用量增加的屏幕截图位于以下链接中。内存使用情况继续这样,直到它已经咀嚼了大约150MB。这一切都在一个只有一个GameObject for init脚本的场景中(没有艺术或任何东西)。

https://www.dropbox.com/s/3b6skexz6xhug5g/Screenshot%202014-03-28%2014.54.26.png

3 个答案:

答案 0 :(得分:1)

正如Unity文档建议的那样,你应该在“使用”语句块中封装你对WWW对象/缓存例程的使用。

using System;
using UnityEngine;
using System.Collections;

public class CachingLoadExample : MonoBehaviour {
public string BundleURL;
public string AssetName;
public int version;

void Start() {
    StartCoroutine (DownloadAndCache());
}

IEnumerator DownloadAndCache (){
    // Wait for the Caching system to be ready
    while (!Caching.ready)
        yield return null;

    // Load the AssetBundle file from Cache if it exists with the same version or download and store it in the cache
    using(WWW www = WWW.LoadFromCacheOrDownload (BundleURL, version)){
        yield return www;
        if (www.error != null)
            throw new Exception("WWW download had an error:" + www.error);
        AssetBundle bundle = www.assetBundle;
        if (AssetName == "")
            Instantiate(bundle.mainAsset);
        else
            Instantiate(bundle.Load(AssetName));
                // Unload the AssetBundles compressed contents to conserve memory
                bundle.Unload(false);

    } // memory is freed from the web stream (www.Dispose() gets called implicitly)
}
}

“using”语句是一个C#功能,可确保“Dispose()”方法正常工作(在很多情况下,为您自动调用)。

如MS的文档中所述:http://msdn.microsoft.com/en-us/library/yh598w02.aspx

“[using]提供方便的语法,确保正确使用IDisposable对象。”

我猜您的内存泄漏是由于这些功能无法按预期执行(可能是由于配置不当,不确定)。

答案 1 :(得分:1)

我在iPad上的AssetBundle下载时遇到过类似的问题。但是,就我而言;

  • 我从服务器下载assetbundle(不使用缓存)并稍后加载。在一个资产包中,如果资产包的图像数超过100或者说200,则会增加内存。
  • 这不是UnityDestroyWWWConnection或“使用”问题。我正在下载60MB资产包(在资产包生成时使用最佳压缩),下载时使用大约450MB。
  • 我检查了仪器的结果,并在下载资产包时看到了大量的小malloc。 You can check the instrument screenshot from here.

我的猜测 - 不确定:Unity在继续下载时从资产包中提取信息,这会给内存带来错误。它首先得到标题信息,并且知道它是unity3d对象,并且因为它使用www类下载它准备WWW asset bundle

我的解决方案是:

  • 压缩assetbundle并将服务器设为zip。
  • 下载资产包zip并在iPad上解压缩(使用SharpZipLib)

答案 2 :(得分:0)

我们的应用程序遇到了类似的问题。我们从WWW加载了大量纹理,并注意到iOS是唯一一个从内存泄漏的平台。我们最终在http://forum.unity3d.com/threads/www-memory-leak-ios.227753/找到了我们的解决方案。基本上,Unity 4.3中存在一个已知问题,即从www调用中泄漏数据。这应该固定在4.5中。在此期间,您可以按照Alexey的建议修改生成xcode项目中的代码或更新到4.5:

  

4.5将有修复。   基本上你需要:   搜索   extern" C" void UnityDestroyWWWConnection(void * connection)   在WWWConnection.mm

[delegate.connection cancel]; 
delegate.connection = nil;
[delegate.data release]; // <-- ADD THIS
[delegate release];
相关问题