一直以为Unity内存中只有一份物理资源,包括Texture,Mesh,Shader,Material等,这是错误的,如果用Resource去Load资源,Unity会保证资源是唯一的,如果使用AB,再使用和AB unload不当的情况下,会导致内存中有多分Texture,Mehs,Shader,Material等。
出现这种情况主要是因为A资源通过AB加载完成后,clone一份A_1资源,ab被unload(false),如果此时再去加载一次A资源,并且前面并且A_1在此过程中一直没Destroy,第二次通过ab加载出来并clone为A_2资源,ab被unload(false)。此时内存中将会有两份相同的物理资源。因此,要注意,如果Unity clone出来的GameObject未被Destory,ab一定不要unload(false)。用同一个ab clone出来的GameObject能保证物理资源的唯一。
解决方案:一种是通过弱引用,来对ab中的asset进行弱引用,但检测到ab中所有的asset没有被引用时,ab就可以执行unload(false)了,unload(ture)一定要谨慎使用。
一种方案是自己做一个引用计数,一定要保证ab中asset克隆和删除的++和--,不然一旦引用计数维护失败,将会导致ab过早或过晚甚至内存上的泄露。
IEnumerator loadScene(string sceneName)
{
string fileFullPath = "file://" + Application.streamingAssetsPath + "/AssetBundle/" + sceneName+"."+AB_END;
WWW www = new WWW (fileFullPath);
yield return www;
if (www.error == null)
{
Debug.LogError("LoadSuccess " + www.assetBundle.LoadAllAssets().Length);
if (www.assetBundle != null)
{
GameObject temp = www.assetBundle.LoadAsset("Assets/Resources/npc/npc_9006_mutong01/npc_9006_mutong01.prefab", typeof(GameObject)) as GameObject;
GameObject go = GameObject.Instantiate(temp) as GameObject;
go.name = "mutong_" + (index++).ToString();
GameObject go2 = GameObject.Instantiate(temp) as GameObject;
go.name = "mutong_" + (index++).ToString();
GameObject go3 = GameObject.Instantiate(temp) as GameObject;
go.name = "mutong_" + (index++).ToString();
}
www.assetBundle.Unload(false);
//AssetBundle abScene=www.assetBundle;
//SceneManager.LoadScene (sceneName);
}
else
{
Debug.LogError ("fileFullPath:"+fileFullPath+" error:" + www.error);
}
www.Dispose ();
www = null;
}