WWW() and memory leaks

Hi,

I’ve got a problem with memory leaking on PC, using C#. I’m using the WWW class, but not using the “yield return” methodology since it seem not to work.

After loading an image, it is set as texture to GUI label.

This code properly loads an image from the web, but if I repeat the action the old image(s) stays in memory and won’t go away, even if I don’t use it in the code anymore.

public class GuiApp : MonoBehaviour
{

public string ImageUrl = "http://some.image.url";
public Rect RenderingRect;

private WWW _request;

Start(){
    _request = new WWW(ImageUrl);
}

Update(){
    if (_request.isDone) {
        // draw label with texture
        GUIContent content = new GUIContent();
        content.image = _request.texture;
        GUI.Label(RenderingRect, content);
        
        // dispose WWW
        _request.Dispose();
    }
}

}

So, is this a problem in my approach, a problem with Unity or with Mono? :slight_smile:

Any help would be appreceated!

Danko

The problem is neither Unity nor Mono, the problem is your code.

Manually loaded textures must be manually destroyed, they will not be GCed.

Instead of the pseudocode above, I’m posting the actual code (attached on camera):

using UnityEngine;
using System.Collections;

public class WWWTest : MonoBehaviour
{
    public string ImageUrl = "http://images.earthcam.com/ec_metros/ourcams/fridays.jpg";
    public Rect RenderingRect = new Rect(10, 60, 600, 400);

    private WWW _request;
    private Texture _texture;

    void Start()
    {
        //_request = new WWW(ImageUrl);
    }

    private void LoadImage()
    {
        Debug.Log("Loading image...");
        _request = new WWW(ImageUrl);
    }

    void Update()
    {
        if (null != _request  _request.isDone) {

            Debug.Log("Image loaded.");

            // get texture
            _texture = _request.texture;

            // dispose WWW
            _request.Dispose();
            _request = null;
        }
    }

    void OnGUI()
    {
        if (GUI.Button(new Rect(10, 10, 100, 40), "Load"))
            LoadImage();

        if (null != _texture)
        {
            // draw label with texture
            GUIContent content = new GUIContent();
            content.image = _texture;
            GUI.Label(RenderingRect, content);
        }
    }
}

That does not destroy the old texture too before setting it to the new one.

It does work fine, actually, and using Update like that isn’t very efficient since you’re constantly polling values when it’s not necessary.

Anyway, as the docs say about WWW.texture: “Each invocation of texture property allocates a new Texture2D. If you continously download textures you must use LoadImageIntoTexture or Destroy the previously created texture.”

–Eric

Thanks for help guys.

The Destroy feature is what i’ve been looking for. It clears the old texture:

void Update()
    {
        if (null != _request  _request.isDone) {

            Debug.Log("Image loaded.");

            // destroy old texture
            Destroy(_texture);

            // get texture
            _texture = _request.texture;

            // dispose WWW
            _request = null;
        }

Also, I’ll reconsider the yield method.