我们将资产包存储在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
答案 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下载时遇到过类似的问题。但是,就我而言;
我的猜测 - 不确定:Unity在继续下载时从资产包中提取信息,这会给内存带来错误。它首先得到标题信息,并且知道它是unity3d对象,并且因为它使用www类下载它准备WWW asset bundle。
我的解决方案是:
答案 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];