Memory leak?

Our game has memory problems when run for an extended time and we suspect a memory leak having tested it with Xcode’s instruments.

Overall, we have a small front-end scene which loads in the game scene. When this level is completed (or the player quits), the front-end scene is reloaded.

We thought this reloading of the front-end scene would destroy all objects and effectively leave the device with the same memory as when the front-end was first run.

However, when we use the Xcode Object Allocation tool we see the net allocation gradually increasing each time the front-end scene is reloaded.

Oddly if we repeatedly load the same scene from the front-end and then return to the front-end scene, the memory does seem roughly consistent. But, each time we load a different scene and return to the front-end, the net allocation has increased (by several 100k each time).

Obviously, over a period of playing different levels we eventually get memory errors and the game crashes.

So, our question is - does Unity not really destroy everything form a prior scene when Application.LoadLevel is called? What things can a scene/script do to leave something that must be manually destroyed? We currently do call Application.GarbageCollectUnusedAssets and System.GC.Collect each time we load a game level.

the GC collection will not help anything, it only controls the .NET objects, not the UnityEngine objects to which internal references exist.

You would use the corresponding function in the application class to purge unused resources.

The load level directly potentially will also not free it. At least on 1.0.x it was the second load level that completely freed it, so you normally had a “transition dummy scene” in between which normally held the loading screen (single guitexture) and nothing else other than the loadlevel code for the real target scene, passed in through a variable or whatever you prefer (on the global nondestroyed manager object you have)

My guess is that you are using OnGUI which you really shouldn’t do on the iphone. If you use SpriteUI instead you get much more performance and a lower memory footprint too.

I’ve seen exactly the same thing and reported it as bug 285871. No resolution yet.

The only thing I can advise is to try and reduce memory as much as possible - I’ve compressed all the full screen textures the game uses, and while the results look visually poor (cartoon-style graphics don’t compress well using pvrtc), at least it doesn’t crash so easily.

@dreamora - thanks for the info. We aren’t using OnGUI, but we’ll look into trying a dummy second scene to see if that frees anything.

@Oaf - thanks too. Have you tried the dummy second scene suggested by dreamora? As for memory, we’ve cut back all we can, and sadly any savings will only save enough space to last for a while until a few more scene load leaks eat it up again!

I’ll post later with our results of the dummy scene loading…

bluesky,
please submit your project for investigation.

Putting in a dummy scene hasn’t helped our problem unfortunately.

@mantasp - our project is huge. We’ll try making a smaller version to see if the problem exists here too. However, Oaf talked of a similar bug already being submitted - have you been able to look at that? Thanks.

My project is huge too, but at the moment I’m scraping by by using Application. GarbageCollectUnusedAssets( ) and crossing my fingers :smile:

Bug 285871 is about compressed sounds not playing after movie playback. Maybe bug number mistype ?

There’s two parts to that bug - the first part is about compressed audio following video, the second part is about memory leaks - or at least it was when I filed it!

Sorry, should have filed it as two separate bugs, but at the time I thought the two were related.

Opened 9/14/2009 4:54 PM
Report type: Problem With Player
Reproducable: Always

iphone: Bug One:

Start the game, and let the intro video play through. Notice the video seems to loop briefly, playing again the first few frames of video. This happens in all the videos in the game. Then, no music plays throughout the game - even within separately loaded scenes.

If you quit the game, restart, and interrupt the intro video, music plays normally.

Bug Two:

From the main menu, choose Single Game. Then select Bowling, and click the tick. Bowling loads. Tap through the instruction and intro screens. Click on the Pause button and choose Quit. Next, select Cooking from the menu, click the tick button, wait for the game to load, tap through the instruction and intro screens, click the Pause button and Quit.

Do the same again with Crazy Lanes, Paint, and so on.

Depending on how much memory is available, the game will crash out at some point with an out of memory error.

However, if you go load the game again, but repeatedly choose the same game over and over (eg Bowling), the game doesn’t leak memory. I’ve done this with each individual game.

I’ve also checked to make sure I’m releasing everything before and after each level is loaded, and perform frequent GC calls.

I’ve attached the Player project.

Many thanks,

Mark

It is much easier to track and solve bugs when they are covering only one issue. I would recommend to resubmit bug #2 as separate bug report. There is no need to submit project once again, just add bug number as reference.

P.S. we love small repro cases! :slight_smile:

I can’t reproduce the problem now I’ve compressed most of the big textures and free up everything using GarbageCollectUnusedAssets(). I’ve resolved the music-following-video bug by converting all my mp3s into wavs. Ugly, but it works…

I’ve also found that when doing things like playing videos, freeing up objects, and garbage collecting, Unity needs room to “breathe”. So, for example, doing all those things at once (ie without returning out of Update) seems to upset things.

So, I now have a standard procedure for cleaning up before playing the next game’s video and switching to that games scene, which allows Unity to breathe long enough to perform all the things I’m throwing at it:

        switch( State )
        {
                . . . 

			case STATE_CLEANUP:
					shutdownCleanup( );
					GCcounter = 0;
					State = STATE_GC;
					break;

			case STATE_GC:
					GCcounter++;
					if( GCcounter == CLEANUP_DELAY_FRAMES )
					{
						if( Application.isPlayer )
							Application.GarbageCollectUnusedAssets( );

						GCcounter = 0;
					}

					State = STATE_PLAY_NEXT_SCENE_VIDEO;
					break;

			case STATE_PLAY_NEXT_SCENE_VIDEO:
					GCcounter++;
					if( GCcounter == CLEANUP_DELAY_FRAMES )
					{
						GCcounter = 0;

						ShowVideo( nextScene + ".mp4" );
						
						State = STATE_LOAD_SCENE;
					}
					break;

			case STATE_LOAD_SCENE:
					GCcounter++;
					if( GCcounter == CLEANUP_DELAY_FRAMES )
						Application.LoadLevel( nextScene );
					break;
        }

This lives within Update( ). Set State to STATE_CLEANUP when you want to leave the scene, setting nextScene to the name of the scene you want to load (and the video you want to play, in my case). I’ve included the video player case, as I’ve found it needs a clean environment to successfully play – previously, it would crash if I hadn’t freed everything up beforehand.

shutdownCleanup() is where I destroy all my objects and set them to null.

CLEANUP_DELAY_FRAMES is 10 - so there’s 1/3 of a second before each operation.

Give this a go in your project - it might help while the Unity boys find their leak :slight_smile:

Hope it helps!