I have searched and read posts related with Unity Memory leak in this forum and still couldn’t figure out to solve my problem.
I have dynamically created simple game objects ( around 70 of them) with only one 2D texture on each one of them. The memory usage increased more than 300M bytes, each one of the 2D texture is a png pic (310 X 310 pixels, 70K in size). more than 4M each object took from the heap memory! Even though each one of them is very simple and small gameobject. Any ideas on this?
The second problem is that I can’t free up the memory they used by calling Destroy(). So the next time I load up the same scene, it will increase memory usage another 300+M. By then my poor computer will hang and stopped responding. Attached is the code I uses:
using UnityEngine;
using System.Collections;
using System;
using Newtonsoft.Json.Linq;
using SmartFoxClientAPI;
using SmartFoxClientAPI.Data;
using LitJson;
public class GetCommodityImage : MonoBehaviour {
private Hashtable htCommodity=null;
private Hashtable htCommodityArray=new Hashtable();
private string commodityModelURL=SystemParamInit.getPhpServerURL()+“seller/getCommodityModelInfo.php”;
private JArray commodityModelArray;
public IEnumerator LoadCommodityModel(string roomname){
WWW getwww = new WWW (commodityModelURL+“?sqlwhere=roomname='”+roomname+“'%20and%20isjoinshop=1”);
yield return getwww;
string myHash = getwww.data;
if(myHash!=“”){
JObject o = JObject.Parse(myHash);
commodityModelArray = (JArray)o[“commodityModelInfo”];
GameObject commodityPic = new GameObject();
commodityPic.name=“CommodityPic”;
for(int i=0;i<commodityModelArray.Count;i++){
int isjoinshop = int.Parse((string)commodityModelArray*[“isjoinshop”]);*
float position_x = float.Parse((string)commodityModelArray*[“position_x”]);
float position_y = float.Parse((string)commodityModelArray[“position_y”]);
float position_z = float.Parse((string)commodityModelArray[“position_z”]);
float rotation_x = float.Parse((string)commodityModelArray[“rotation_x”]);
float rotation_y = float.Parse((string)commodityModelArray[“rotation_y”]);
float rotation_z = float.Parse((string)commodityModelArray[“rotation_z”]);
float scale_x = float.Parse((string)commodityModelArray[“scale_x”]);
float scale_y = float.Parse((string)commodityModelArray[“scale_y”]);
float scale_z = float.Parse((string)commodityModelArray[“scale_z”]);
GameObject obj=(GameObject)Instantiate(Resources.Load(“commodity”),new Vector3(Convert.ToSingle(position_x), Convert.ToSingle(position_y),Convert.ToSingle(position_z)), new Quaternion(Convert.ToSingle(rotation_x),Convert.ToSingle(rotation_y),Convert.ToSingle(rotation_z),1));
obj.name = (string)commodityModelArray[“commodity_id”];
obj.transform.parent =commodityPic.transform;
obj.tag = “Goods”;
obj.transform.localScale = new Vector3(Convert.ToSingle(scale_x),Convert.ToSingle(scale_y),Convert.ToSingle(scale_z));
ObjectDetail commodityDetail = (ObjectDetail)obj.GetComponent(“ObjectDetail”);
_commodityDetail.names = (string)commodityModelArray[“name”];_
commodityDetail.price = float.Parse((string)commodityModelArray[“real_price”]);
commodityDetail.commodityid = int.Parse((string)commodityModelArray[“commodity_id”]);
string model_image = (string)commodityModelArray[“model_image”];
string url = SystemParamInit.getCommodityModelPicURL()+roomname+“/”+model_image;
StartCoroutine(AutoChangeColor(url,obj)); //red pic from server and attach it to model
_}else{
commodityModelArray = null;
}
}
public IEnumerator AutoChangeColor(string picUrl,GameObject modelObj) {
WWW www= new WWW (picUrl);
yield return www;
modelObj.transform.GetChild(0).renderer.material.mainTexture = www.texture;
}
}*_
modelObj.transform.GetChild(0).renderer.material.mainTexture = www.texture;
This line of code is the culprit.
If I change the texture from dynamically got from WWW to statically attached in the prefab, memory increase is minimal.
Above line of code called 70 times can increase memory usage more than 300M. the texture file is only 77k, 310X310 in pixels.
What could possibly be wrong here.
for(int v=0;v<GameObject.Find(“CommodityPic”).transform.childCount;v++){
Destroy(GameObject.Find(“CommodityPic”).transform.GetChild(v).gameObject);
}
Destroy(GameObject.Find(“CommodityPic”));
GameObject.Find(“Commodity”).SendMessage(“LoadCommodityModel”,shopename);
Above is the codes that do the destroy. And it didn’t work. the memory is not freed. How come?
Please read the docs on www.texture on what you are doing significantly wrong.
also the texture is over 400k actually (its bitmap size * 1.33 for mipmap so 3103104byte * 1.33) and you leak all of them
that though does not give 300mb, but already a fine little nothing of 30 / 60mb (depending on where they reside. as they are not rendered at the time there is a tendency towards 60mb)
// Get the latest webcam shot from outside “Friday’s” in Times Square
var url = “http://images.earthcam.com/ec_metros/ourcams/fridays.jpg”;
function Start () {
// Start a download of the given URL
var www : WWW = new WWW (url);
// Wait for download to complete
yield www;
// assign texture
renderer.material.mainTexture = www.texture;
}
Dreamora, above is the sample codes I copied from www.texture document, the only difference I can tell is that I used png file format, and the sample used jpg. From the document, I didn’t see that’s the problem.
And also the increase of memory usage when the pics are loaded is huge, not 400k each as you calculated, it is average 4M each. What went wrong, and where exactly my code was wrong? Dreamora, please be more specific. Thank you very much for your help!
your code was wrong in the sense of: you don’t destroy the previous texture so you leak the old texture all the time.
4mb sounds like a bit much.
reasonably it could be that it instantiates a 512x512 texture as thats the next pow2, in which case it would be 1.4mb / texture, potentially 2.8 if it is not rendered and therefor in the managed texture ram block of DX + the regular system RAM where unity holds it.
Thanks Dreamora, I will work on it accordingly and see how that works.
Dreamora, I have changed all my pic file resolutions from 310310 to 256256, and now the memory increase changed from 300M to about 70M, amazingly it worked.
I also changed to use compression, it has an additional reduce of memory usage about 50%. Wonderful.
Now back to the last question, where exactly should I destroy my object before it leaks. You saw my destroy codes, why doesn’t it work? Why do you say I have already leaked memory before I call destroy?
I recommend to read the documentation on www.texture
public IEnumerator AutoChangeColor(string picUrl,GameObject modelObj) {
WWW w = new WWW(picUrl);
yield return w;
// Debug.Log(“image loaded”);
Destroy(modelObj.transform.GetChild(0).renderer.material.mainTexture);
Texture2D tex = new Texture2D(256,256, TextureFormat.DXT1, false);
w.LoadImageIntoTexture(tex);
modelObj.transform.GetChild(0).renderer.material.SetTexture(“_MainTex”, tex);
w.Dispose();
w = null;
}
Dreamora, above is the changed codes. Now everytime I reload the scene, the memory increase is about 10M, 80 small gameobjects with 256*256 pixel pic attached. Seems like the memory leak is still there. Now I destroy old texture before assign new. Still, anything wrong with my codes? Really appreciated, and I find it more helpful to search and read through the posts than Unity documents, Unity documents has so less information.