2

我们将资产包存储在 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。这一切都在一个场景中,其中只有一个用于初始化脚本的游戏对象(没有艺术或任何东西)。

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

4

3 回答 3

1

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

  • 我正在从服务器下载assetbundle(不使用缓存)并稍后加载。在一个资产包中,如果资产包的图像超过 100 个或比如说 200 个,它会增加内存。
  • 这不是 UnityDestroyWWWConnection 或“使用”问题。我正在下载 60MB 的资产包(在生成资产包时使用最佳压缩),下载时它使用了大约 450MB。
  • 我检查了仪器的结果,在下载资产包时看到了大量的小 malloc。您可以从此处查看仪器屏幕截图。

我的猜测 - 不确定:Unity 在继续下载时从资产包中提取信息,这会导致内存错误。它首先获取标头信息,并了解它是 unity3d 对象,并且因为它使用 www 类下载它为WWW 资产包做准备。

我的解决方案是:

  • 压缩assetbundle并将服务器作为zip。
  • 在 iPad 上下载资产包 zip 并解压(使用 SharpZipLib)
于 2014-09-22T14:17:09.610 回答
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 对象。”

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

于 2014-04-10T17:07:28.983 回答
0

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

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

[delegate.connection cancel]; 
delegate.connection = nil;
[delegate.data release]; // <-- ADD THIS
[delegate release];
于 2014-08-08T18:16:59.647 回答