[Solved] Help on Unity memory leaks.

There is only a default camera and a single GameObject.

Why destroyed game objects are still in-memory ?
I’ve tried to call the GC manually, Resources.UnloadUnusedAssets and a bunch other hacks without success. My game needs to create GameObjects on the fly… ObjectPooling of course could be done but since the player will be playing for hours (I hope so) and there are tons of different sprites I think this would still be a problem.
I tried to reproduce the problem in the simplest possible code as bellow:

public class Game : MonoBehaviour {

private List objects;

// Use this for initialization
void Start () {
this.objects = new List();
}

// Update is called once per frame
void Update () {
foreach(var item in this.objects)
{
Destroy(item);
}
this.objects = new List();
for (var i=0; i<=1000; i++)
{
GameObject gb = new GameObject();
gb.name = i.ToString();
SpriteRenderer renderer = gb.AddComponent();
renderer.sprite = Resources.Load(“Sprites/grass”, typeof(Sprite)) as Sprite;
gb.transform.position = new Vector3(i, transform.position.y, transform.position.z);
this.objects.Add(gb);
}
}

I know that this doesn’t help your question about why GC isn’t removing the destroyed objects… I’m not sure yet on how GC works, entirely, so I can’t answer that.

I do however wonder why “the player will be playing for hours” is a reason not to use object pooling. To me, that’s a bigger reason TO use object pooling. Especially if you’re destroying thousands of objects.

Also, I wish I knew for sure (maybe someone else can confirm), but I’m not sure you should be using Resources.Load in that loop to load the same sprite in over and over. To me it makes more sense to store this reference in a sprite variable… outside your update, even… possibly even through the inspector. That’s a question I’ve been curious about with materials for 3d objects, actually.

Hi cstooch!
Thanks for your answer. I’m using object pooling but the problem is: I’ve too many different objects. I can’t keep a pool of every single object in the game, think of a giant “tiled” RPG map… I’ve already tried to call Resources.Load a single time in the start function and preserve it’s state… it doesn’t help…

USE CODE TAGS:

public class Game : MonoBehaviour {

    private List<GameObject> objects;

    // Use this for initialization
    void Start () {
        this.objects = new List<GameObject>();
    }

    // Update is called once per frame
    void Update () {
        foreach(var item in this.objects)
        {
            Destroy(item);
        }
       
        //this.objects = new List<GameObject>();
        //you could call clear instead of making a new one
        this.objects.Clear();
       
        for (var i=0; i<=1000; i++)
        {
            GameObject gb = new GameObject();
            gb.name = i.ToString();
            SpriteRenderer renderer = gb.AddComponent<SpriteRenderer>();
            renderer.sprite = Resources.Load("Sprites/grass", typeof(Sprite)) as Sprite;
            gb.transform.position = new Vector3(i, transform.position.y, transform.position.z);
            this.objects.Add(gb);
        }
    }

In what way do you know they’re staying in memory? Which memory are they staying in?

Note… there is 2 sides to a UnityEngin.Object (like GameObject and Components). There is the Unity/C++ side, and the mono/C# side.

When you call Destroy on an object the Unity/C++ side is told to destroy it. This usually happens at the end of the frame (not immediately, hence the DestroyImmediately method which can be used at Editor time).

But this leaves the mono/C# object in memory on the mono side. This is because unity has to let the garbage collector clean that up. The way the garbage collector works is that every once in a while it will go through the heap and any object that isn’t referenced by anything will get cleared out. (note, referenced by anything of substance… if its referenced by an object that isn’t referenced, then it’ll still get cleaned).

So… which one, and how do you know, it’s getting stuck in memory?

Resources.Load uses a cached version if you’ve already loaded it.

Ahh, thanks for that clarification! :slight_smile:

How do you know this? I mean really? Memory management in Unity is a bit of a black art. So unless you show me some evidence that the objects are still in memory, I’m going to run with user error.

Note to self: Got to finish that GC for beginners tutorial…

2 Likes

Why are you destroying and creating sprites every frame?

2 Likes

Hi BoredMormon, I’m watching the memory usage of the process after the game is compiled.

Here…

I don’t think you should force the GC to collect
Use object pooling if there’s any benefit.

Work on your game and maintain good practices as you build it up, rather than prematurely worrying about the case of what might be.
Later on , down the road if you really see problems (not like your attempted example, for instance)… but a real game example, then you could investigate further into the matter to see if there’s something to be improved upon.

Those would be my suggestions. :slight_smile:

Hi methos, thanks for your comment. Actually this is already a problem at my game I just created that script to abstract the complexity of the game. Although I do agree with your comment this is a real problem for me right now. It seems that whenever you add a SpriteRenderer component to some object the memory never gets released and keep growing. Pooling is an obvious improvement but it does not solve the problem at all when do you have so many different objects that you can’t (?) create so many different pools. Right now I’m trying a approach to pool the objects and “transform” an object into another on the flow…

As in the process from windows task manager? That’s the wrong place to look.

When a process is running in Windows, it asks the OS for a chunk of memory. The OS gives it a chunk. When it needs more, it asks the OS for another chunk. But if a process stops using that memory, it doesn’t give it back to the OS, instead it keeps it for the next time it might need that memory. So ultimately the memory usage of a process isn’t a good place to look. The actual game memory usage will be obscured by the magic done by the OS and the Mono framework.

Try checking the memory use via the profiler instead.

1 Like

Okay, maybe I didn’t understand the design of your game.how many sprites you talking about here, and how many different ones?
Obviously the example, though trying to illustrate your point, has to be overkill lol.

Memory is managed… so, cleaned up when not referenced, and at intervals, and kept around to be re-used at times… on and on… honestly, I don’t know it all, for sure…

Perhaps with some more info on your game setup, you could get more concrete answers/assistance, rather than presuming “all is wrong/bad”.

Plus, it would help to know what a “problem amount of memory” means to you, maybe.

My game is pretty similar to this:
https://www.google.com.br/search?q=tibia&source=lnms&tbm=isch&sa=X&ved=0ahUKEwj15La19tLUAhWJx5AKHWogBqcQ_AUIBigB&biw=1920&bih=950#tbm=isch&q=tibia+online+game&imgrc=QxGvbgCH7wwC9M:

There are already more than one thousand different sprites… And since the game is not “scene based” as the player can walk a lot I need to keep an eye on memory usage. Creating one thousand different object pools does not seems like a good choice neither… I trying right now to create a pool of objects and “mutate objects (swaping sprites, etc)” on the flow so I don’t need too many different pools.

And by eating too much memory, I mean the game will crash after like 10 minutes.

Hi, thanks for sharing your knowledge but in my case we are not talking about the game wasting a few more megabytes. We are talking about an out of memory error in less than 10 minutes. Memory usage is growing pretty fast. I’ve tried to watch it on Unity profiler but it doesn’t help me a lot.

You use a sprite atlas (atlases)?

Profiler screenshots? I’m no expert on memory management, but there are others that might be able to help.

A thousand different sprites on screen at once? That sounds excessive… How big is each Sprite? You may need to start looking into a more advanced system then sprites.

Edit: In general I’m not convinced that its the GameObjects or SpriteRenderes that are your problem, rather its the sprites themselves.

They are not on the screen at once… As the player moves it will find different sprites hence the question because I need to carefully avoid growing memory usage because the player will eventually see a whole lot of different sprites… (It’s an online game, there is no “loading”… players walks freely in a pretty big “squares” map. By the way: sprites are 32x32.

Right… but that is far from the simplest solution, very much on the other end of the spectrum. The overhead of the gameobject and spriterenderer being created and destroyed 30k - 60k times a second is a massive amount of complexity. There should never be a case where you do that, there are many ways to simplify based on need. Obviously, pooling, but also just creating the sprites and swapping the image in the renderer. The simplest would be to generate the mesh and just recalculate the uvs. That should have nearly no impact on memory over time.
Here is 1.3million tiles (128x128) running with minimal resource expenditure :
https://www.youtube.com/watch?v=Vp2kFsWQwFg

Creating a complex loop to do something that realistically you would never actually do in game isn’t a reasonable approach to optimization. Start with the actual use case, and refine from there. The use case described is a simple map. Unless you are building it for an 8-bit era console where you had to redraw every tick, creating and destroying is the wrong approach.

2 Likes