Author Topic: Tour about texture memory release when change level  (Read 4672 times)

fangguanya

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 1
  • Posts: 3
    • View Profile
Tour about texture memory release when change level
« on: June 16, 2014, 05:40:13 AM »
 ;D Experience sharing, not question!

 :(I found that when I changed my scene at run-time, the atlases that used in previous scene were still referenced and were not releasing at all!! that's wasting memory for me!
So I went through this topic, and I found one related topic:
http://www.tasharen.com/forum/index.php?topic=1979.msg10010#msg10010
With solutions in this topic, I tried
1.panel.Refresh();
2.UIDrawCall.ReleaseAll();
and so on.
Finally I get it work at Editor with code below:
  1. public void SwitchToScene()
  2.     {
  3.         Application.LoadLevel(1);
  4.         NGUIText.bitmapFont = null;
  5.         NGUIText.dynamicFont = null;
  6.         foreach (UIPanel panel in GameObject.FindObjectsOfType<UIPanel>())
  7.         {
  8.             panel.Refresh();
  9.         }
  10.  
  11.         StartCoroutine(ClearScene());
  12.     }
  13.  
  14.     IEnumerator ClearScene()
  15.     {
  16.         yield return new WaitForEndOfFrame();
  17.         Resources.UnloadUnusedAssets();
  18.     }
  19.  
And the memory of unused texture will be free in *Editor* mode!
But at run-time, the memory was not free at all!! so I keep going through, I found NGUITools.DestroyImmediate is different between editor and run-time vertion. In Editor, the object will destroy immediately, but at playing, the object will destroy at the end of the frame, so i add a 'WaitForEndOfFrame' coroutine at my code,
Yeah, it doesn't help, texture still there! I debugged that code through and found that Unity3D call my coroutine before UIDrawCall.OnDestroy!

  1. static public void Destroy (UIDrawCall dc)
  2.         {
  3.                 if (dc)
  4.                 {
  5.                         if (Application.isPlaying)
  6.                         {
  7.                                 if (mActiveList.Remove(dc))
  8.                                 {
  9.                                         NGUITools.SetActive(dc.gameObject, false);
  10.                                         mInactiveList.Add(dc);
  11.                                 }
  12.                         }
  13.                         else
  14.                         {
  15.                                 mActiveList.Remove(dc);
  16.                                 NGUITools.DestroyImmediate(dc.gameObject);
  17.                         }
  18.                 }
  19.         }
  20.  
Yes, you found it! UIDrawCall doesn't release at run-time! it was just disable! still weird about it ? hahah
  1.  
  2.     void OnDisable()
  3.     {
  4.         depthStart = int.MaxValue;
  5.         depthEnd = int.MinValue;
  6.         panel = null;
  7.         manager = null;
  8.         mMaterial = null;
  9.         mTexture = null;
  10.  
  11.         NGUITools.DestroyImmediate(mDynamicMat);
  12.         mDynamicMat = null;
  13.        
  14.         // !< WARN:codes that I add, the referenced material at mDynamicMat was released but not the real one!
  15.         if (mRenderer != null)
  16.         {
  17.             mRenderer.sharedMaterials = new Material[] { };
  18.         }
  19.     }
  20.  

All of above is all my experience to free the UIAtlas memory.
Excuse for my poor English, and thanks for reading, I hope this will help you!.

fangguanya

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 1
  • Posts: 3
    • View Profile
Re: Tour about texture memory release when change level
« Reply #1 on: June 16, 2014, 06:17:16 AM »
;D Experience sharing, not question!

 :(I found that when I changed my scene at run-time, the atlases that used in previous scene were still referenced and were not releasing at all!! that's wasting memory for me!
So I went through this topic, and I found one related topic:
http://www.tasharen.com/forum/index.php?topic=1979.msg10010#msg10010
With solutions in this topic, I tried
1.panel.Refresh();
2.UIDrawCall.ReleaseAll();
and so on.
Finally I get it work at Editor with code below:
  1. public void SwitchToScene()
  2.     {
  3.         Application.LoadLevel(1);
  4.         NGUIText.bitmapFont = null;
  5.         NGUIText.dynamicFont = null;
  6.         foreach (UIPanel panel in GameObject.FindObjectsOfType<UIPanel>())
  7.         {
  8.             panel.Refresh();
  9.         }
  10.  
  11.         StartCoroutine(ClearScene());
  12.     }
  13.  
  14.     IEnumerator ClearScene()
  15.     {
  16.         yield return new WaitForEndOfFrame();
  17.         Resources.UnloadUnusedAssets();
  18.     }
  19.  
And the memory of unused texture will be free in *Editor* mode!
But at run-time, the memory was not free at all!! so I keep going through, I found NGUITools.DestroyImmediate is different between editor and run-time vertion. In Editor, the object will destroy immediately, but at playing, the object will destroy at the end of the frame, so i add a 'WaitForEndOfFrame' coroutine at my code,
Yeah, it doesn't help, texture still there! I debugged that code through and found that Unity3D call my coroutine before UIDrawCall.OnDestroy!

  1. static public void Destroy (UIDrawCall dc)
  2.         {
  3.                 if (dc)
  4.                 {
  5.                         if (Application.isPlaying)
  6.                         {
  7.                                 if (mActiveList.Remove(dc))
  8.                                 {
  9.                                         NGUITools.SetActive(dc.gameObject, false);
  10.                                         mInactiveList.Add(dc);
  11.                                 }
  12.                         }
  13.                         else
  14.                         {
  15.                                 mActiveList.Remove(dc);
  16.                                 NGUITools.DestroyImmediate(dc.gameObject);
  17.                         }
  18.                 }
  19.         }
  20.  
Yes, you found it! UIDrawCall doesn't release at run-time! it was just disable! still weird about it ? hahah
  1.  
  2.     void OnDisable()
  3.     {
  4.         depthStart = int.MaxValue;
  5.         depthEnd = int.MinValue;
  6.         panel = null;
  7.         manager = null;
  8.         mMaterial = null;
  9.         mTexture = null;
  10.  
  11.         NGUITools.DestroyImmediate(mDynamicMat);
  12.         mDynamicMat = null;
  13.        
  14.         // !< WARN:codes that I add, the referenced material at mDynamicMat was released but not the real one!
  15.         if (mRenderer != null)
  16.         {
  17.             mRenderer.sharedMaterials = new Material[] { };
  18.         }
  19.     }
  20.  

All of above is all my experience to free the UIAtlas memory.
Excuse for my poor English, and thanks for reading, I hope this will help you!.

Just forgot one important notice: I remove the UIPanel manual via code, not by default.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Tour about texture memory release when change level
« Reply #2 on: June 16, 2014, 08:54:12 AM »
Thanks, I'll actually add your addition to NGUI itself and see if it causes any downsides.