- Home /
Memory management theory question
So I'm creating book pages, with animations, from existing assets that are downloaded elsewhere in my app, to a device's persistentDataPath.
I have an AssetManager class, marked DontDestroyOnLoad, which I'm thinking is part of my problem, but it's somewhat necessary for displaying subsequent pages. So a user taps on a book from their shelf, and we load a new empty scene for the creation of these Sprite2D objects. The AssetManager class does all of the sprite creation, within a coroutine that uses WWW to load .pngs or .jpgs from that persistentDataPath. When a new page is loaded, that blank scene is then reloaded by the AssetManager, and the sprites are created anew. The problem is that I can't seem to reclaim any of the memory consumed by the sprite images and/or the WWW class that loaded them.
I use WWW.Dispose after each loaded texture has been assigned to the proper sprite, which from what I understand should free up any memory consumed by the texture? At least on Unity 4.5.3 that I'm using?
I also maintain a List of the sprites that are created, and just before creating a new page, I call GameObject.Destroy on each item in the list, and confirmed they are being destroyed with a debug.log in an OnDestroy function attached to each sprite. I'm even doing a manual GC.Collect after destroying everything...
And yet still, the memory continues to climb by 50+MB at every page load. So I suspect that AssetManager is hanging onto references in a way that I don't fully understand. Perhaps due to code like this?
bookUI = NGUITools.AddChild(pageObjects, bookPrefab);
pageSprites.Add(bookUI);
bookUI.GetComponent<UIPanel>().depth = x+2;
backgroundSprite = bookUI.transform.FindChild("SpriteImage").gameObject;
bookSprite = backgroundSprite.GetComponent<BookSprite>();
//Lots of variable setting for the bookSprite, assigning a frames array of filenames to load from persistentDataPath, anim durations, etc.
bookUI of course being the prefab that needs to get destroyed later. But is declaring it in this way making AssetManager hold onto a reference for it, preventing it from being properly cleared from memory on destroy?
So my thinking is that I could add a "Create" function on the BookSprite class and just pass in all the requisite variables needed to create that sprite, so they are properly destroyed, but even then the AssetManager needs to at least have a reference to the sprite after it's instantiated and do a GetComponent to call the Create function, is that still going to be enough to hold onto that reference and prevent the memory from being freed? It's a fair amount of refactoring at this point, I'd rather not waste the time if it won't help things.
I don't know, I can only read www.unitygems.com/memorymanagement so many times, thinking "It's supposed to be automatic, come on!" before I go nuts here...
Answer by Freezy · Aug 20, 2014 at 05:36 PM
Have you tried Resources.UnloadUnusedAssets(); to free up memory after unreferencing assets (aka destroying the GameObject)?
GameObject destruction might be delayed to some point in the future. With OnDestroy() you might be able to start a coroutine on you AssetManager class to clean up after say a few seconds?
Does the profiler indicate where the memory is getting wasted?
As a final resort, create a smaller test version and ship it as a bugreport to Unity. It would not be the first time a memory bugged slipped into the code somewhere.
Wow.... WOW! I'm not even using Resources to generate the sprites themselves, as they come from WWW loading, but I suppose since I was technically instantiating a semi-empty prefab, that Resources was still holding on to that reference... Added a call to Resources.UnloadUnusedAssets(); at the end of my page creation, and VOILA!
I knew about the function, just didn't really think it applied in this case, definitely something I should have tried by now. THAN$$anonymous$$ YOU FREEZY!