Author Topic: Unused Atlas Not Cleaned Up Properly When Changing Scene  (Read 13831 times)

andrew99

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 7
    • View Profile
Unused Atlas Not Cleaned Up Properly When Changing Scene
« on: January 30, 2014, 03:18:18 AM »
Hello,

Sorry if my question had been asked before. I've run into some memory problem I've noticed when developing for some older iOS device.
My game has several atlases, one main UI atlas, and some scene specific atlases for different scenes. The NGUI version I'm using is 3.0.9f2
When I do some profiling in Unity & XCode I've noticed when changing into scenes which uses different atlas, the memory usage keeps increasing,
until eventually the app crashed on weaker old devices.

When I run a profiler in Unity I've noticed that the unused atlas still has references even though no objects are currently using that atlas in the current scene.
Specifically it says ManagedStaticReferences in the profiler (didn't really understand what that mean).

My atlas usage flow is something like this :
Atlas -> atlas assigned to Reference Atlas Prefab -> prefab assigned to various UISprites in Scene (reference atlas prefab is there to make it easier for changing between SD / HD Atlas source)

I've also tried to create a clean project to test this case with a simpler flow where atlas are assigned directly to UISprites, and it is still not cleaned when changing scenes.

I've tried using Resources.UnloadUnusedAsset() and System.GC.Collect(), but it seemed to have no effects, most likely because there's still some references to the atlas.
Is this a problem with NGUI / Unity, or am I doing something wrong with how I design my usage flow?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Unused Atlas Not Cleaned Up Properly When Changing Scene
« Reply #1 on: January 30, 2014, 11:26:23 AM »
Destroy the UI, yield until the end of frame, and only then call Resources.UnloadUnusedAssets().

andrew99

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 7
    • View Profile
Re: Unused Atlas Not Cleaned Up Properly When Changing Scene
« Reply #2 on: January 30, 2014, 12:47:18 PM »
Hmm.. Nope, the unused atlas texture is still referenced.
I tried attaching this script to an empty GameObject in each scene.

  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4.  
  5. public class TestChangeScene : MonoBehaviour {
  6.         public string targetScene;
  7.        
  8.         void Start ()
  9.         {
  10.                 Resources.UnloadUnusedAssets();
  11.         }
  12.  
  13.         void Update()
  14.         {
  15.                 if(Input.GetKeyDown(KeyCode.Space))
  16.                 {
  17.                         TriggerSceneChange();
  18.                 }
  19.         }
  20.  
  21.         public void TriggerSceneChange()
  22.         {
  23.                 UIWidget[] widgets = Resources.FindObjectsOfTypeAll<UIWidget>();
  24.                 foreach(UIWidget tmp in widgets)
  25.                 {
  26.                         Debug.Log("destroying : " + tmp.name);
  27.                         Destroy(tmp);
  28.                 }
  29.                 StartCoroutine(unload());
  30.         }
  31.  
  32.         IEnumerator unload()
  33.         {
  34.                 yield return new WaitForEndOfFrame();
  35.                 Resources.UnloadUnusedAssets();
  36.                 Application.LoadLevel(targetScene);
  37.         }
  38. }

When sampling the profiler inside the second scene, the texture from atlas of the first scene is still referenced.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Unused Atlas Not Cleaned Up Properly When Changing Scene
« Reply #3 on: January 30, 2014, 12:49:28 PM »
Try calling UIDrawCall.ReleaseInactive()

andrew99

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 7
    • View Profile
Re: Unused Atlas Not Cleaned Up Properly When Changing Scene
« Reply #4 on: January 30, 2014, 01:09:16 PM »
Didn't find UIDrawCall.ReleaseInactive() method. I'm currently using 3.0.9f2, do I need to update to f7 to call this method?
Find a ReleaseAll() method though. Tried modifying the previous script into something like
  1. public void TriggerSceneChange()
  2.         {
  3.                 UIWidget[] widgets = Resources.FindObjectsOfTypeAll<UIWidget>();
  4.                 foreach(UIWidget tmp in widgets)
  5.                 {
  6.                         Debug.Log("destroying : " + tmp.name);
  7.                         Destroy(tmp);
  8.                 }
  9.                 UIDrawCall.ReleaseAll();
  10.                 StartCoroutine(unload());
  11.         }
  12.  
After changing scene, the unused atlas is still there, though the reference somewhat change.
I'm testing this in Unity 4.3.3 with the two simple scenes each consisting of an UIRoot, camera, and a sprite with different atlas source.

Rajken

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 2
  • Posts: 12
    • View Profile
Re: Unused Atlas Not Cleaned Up Properly When Changing Scene
« Reply #5 on: January 31, 2014, 11:46:20 AM »
I had the same problem with the drawcall still having a connection to the Atlas when a new level was loaded.
I fixed this by setting mMaterial and mTexture to null in the OnDisable function in UIDrawCall.cs.
I don't know if this will cause some other problem but it looks like it is working for now.

Can you think of any thing that can go wrong by doing this Aren?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Unused Atlas Not Cleaned Up Properly When Changing Scene
« Reply #6 on: January 31, 2014, 12:06:46 PM »
@Rajken: That should be fine, actually. I'll add that in, thanks.

@andrew99: Yes that method was added in a later update.

andrew99

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 7
    • View Profile
Re: Unused Atlas Not Cleaned Up Properly When Changing Scene
« Reply #7 on: February 01, 2014, 04:11:47 AM »
IT WORKED!!!
Adding that on the OnDisable function, and then calling Resources.UnloadUnusedAssets() in the new scene clears the textures properly
Thanks a lot Rajken & ArenMook! Has been splitting my hairs for the past few days looking for a workaround for this problem. ;D ;D

oddurmagg

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 12
    • View Profile
Re: Unused Atlas Not Cleaned Up Properly When Changing Scene
« Reply #8 on: March 03, 2014, 05:27:27 AM »
will be be seeing those changes to OnDisable in a release soon or should we just patch our versions ?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Unused Atlas Not Cleaned Up Properly When Changing Scene
« Reply #9 on: March 03, 2014, 11:24:23 PM »
NGUI doesn't do Resources.Load, so it wouldn't make sense for it to do Resources.Unload. NGUI releases all references to textures now, but it's still up to you to call UnloadUnusedAssets -- prefferably in the same class you used to Load the asset in the first place.

HaroldBalls

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 1
    • View Profile
Re: Unused Atlas Not Cleaned Up Properly When Changing Scene
« Reply #10 on: September 26, 2014, 10:32:29 PM »
I'm having the same problem, but on 2.7 (its an old project)

I tried an approximation of the changes above, and got some weird results, can you recommend some changes to me version to cure the same issue?

Thanks,

Ben

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Unused Atlas Not Cleaned Up Properly When Changing Scene
« Reply #11 on: September 27, 2014, 07:16:02 PM »
I can't. NGUI 2 is extremely out of date and isn't supported, which is why it's free.