Author Topic: Could widgets be caching a hard reference to atlas texture?  (Read 8281 times)

sisso

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 1
  • Posts: 46
    • View Profile
Could widgets be caching a hard reference to atlas texture?
« on: August 29, 2013, 12:27:12 PM »
Hi Guys.

I think that NGui Widget are serializing a directly reference to the atlas texture that cause Unity3d load in memory the unused HD texture.

I added in UIWidget:

  1. // Awake
  2.                 Debug.Log(gameObject ": " (mMat == null ? "no material": mMat.name));
  3.                 Debug.Log(gameObject ": " (mTex == null ? "no texture": mTex.name));
  4.  
  5. // Start
  6.                 Debug.Log("START: " gameObject ": " (mMat == null ? "no material": mMat.name));
  7.                 Debug.Log("START: " gameObject ": " (mTex == null ? "no texture": mTex.name));
  8.  
And receive these logs in editor:

  1. FadingSprite (UnityEngine.GameObject): no material
  2. FadingSprite (UnityEngine.GameObject): MenuAtlasHd
  3.  
  4. START: FadingSprite (UnityEngine.GameObject): MenuAtlasSD
  5. START: FadingSprite (UnityEngine.GameObject): MenuAtlasSD
  6.  
I was debug why some HD textures from atlas/font are being loading in memory. Showed by Resources.FindObjectsOfTypeAll(typeof(Texture). These texture are being loaded even if I delete the AtlasHD.prefab or AtlasHD.mat.

Some considerations:

- this test I execute in Editor
- I using classic solution for multiples atlas resolution in same build: AtlasRef, AtlasHd, AtlasSD.
- AtlasRef have replacement and material cleared before build.
- AtlasRef is pointed from AtlasHD/SD loaded from resource at first scene.
- Every widget is pointing to AtlasRef
- Some time in the past I think that some widgets pointed directly to HD version (could be cached that time?)
- many of theses widgets are stored in prefabs

NGUI master, could you give a look if it really could happens? Or can give me a direction for what I probably is doing wrong?

--  Added

In editor if I select the atlas texture and use contextual menu "Find References in Scene", the unity select the widgets where Awake show HD texture.

« Last Edit: September 03, 2013, 07:27:47 AM by sisso »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Could widgets be caching a hard reference to atlas texture?
« Reply #1 on: August 29, 2013, 04:10:24 PM »
Both material and texture references get cleared when the widget gets disabled *and* when it gets enabled. Check UIWidget.OnDisable -- if (!keepMaterial) material = null, which in turn sets mTex to null inside. Try disabling the UI before doing the build.

sisso

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 1
  • Posts: 46
    • View Profile
Re: Could widgets be caching a hard reference to atlas texture?
« Reply #2 on: August 29, 2013, 04:13:29 PM »
If I remove the [SerializeField] from widget. Bad things will happens?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Could widgets be caching a hard reference to atlas texture?
« Reply #3 on: August 29, 2013, 04:17:16 PM »
Your UITextures will lose texture references.

motionsmith

  • Guest
Re: Could widgets be caching a hard reference to atlas texture?
« Reply #4 on: August 30, 2013, 03:27:24 PM »
I am having this problem. I understand that I need to do two things?

1. Have a "design-time" editor script that somehow loops through all prefabs, nulling "atlas type" references in all "reference atlases". I should run this before making a build.

2. call SetActive(false) on my UIRoot GameObject at design-time (before a build) on all scenes, then enable it (and subsequently all children) after the proper atlas resource is loaded and referenced in the "reference atlas".

Is this correct? Do I need to do anything else? Concerning step one, how can I find and iterate through all my reference atlases?

sisso

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 1
  • Posts: 46
    • View Profile
Re: Could widgets be caching a hard reference to atlas texture?
« Reply #5 on: September 02, 2013, 08:42:20 AM »
If mMat and mTex are used both for real references and caching, it smell that could be refactored in two variables.  :P Thanks, I will test this today.

@motionsmith, This could help you:
  1. static function ApplyPrefabsBuildCustoms() {
  2.                 EditorApplication.NewScene();
  3.                 var paths = FindPaths(["*.prefab"]);
  4.                 for (var path in paths) {
  5.                         var p = AssetDatabase.LoadMainAssetAtPath(path);
  6.                         var obj = PrefabUtility.InstantiatePrefab(p) as GameObject;
  7.                         var changed = false;
  8.                         // do whatever you want with prefab instance
  9.                         // ...
  10.                         if (changed) PrefabUtility.ReplacePrefab(obj, p, ReplacePrefabOptions.Default);
  11.                         GameObject.DestroyImmediate(obj);
  12.                 }
  13.         }
  14.        
  15. static function FindPaths(filters: String[]): String[] {
  16.         var paths = new List.<String>();       
  17.         for (var filter in filters) {
  18.                 var files = Directory.GetFiles(Application.dataPath, filter, SearchOption.AllDirectories);
  19.                 for(var f in files) {
  20.                         paths.Add(NormalizeDataPath(f));
  21.                 }
  22.         }
  23.         return paths.ToArray();
  24. }
  25.  
  26. static function NormalizeDataPath(path: String) {
  27.         var normalizedPath = "Assets" + path.Replace(Application.dataPath, "").Replace('\\', '/');
  28.         return normalizedPath;
  29. }

ChrisR

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 33
    • View Profile
Re: Could widgets be caching a hard reference to atlas texture?
« Reply #6 on: September 02, 2013, 08:56:33 AM »
Hey Sisso,

For us less code-literate, could you give a quick explanation about what that piece of code does?

Since it seems we're dealing with the same issue, it would be much appreciated!

Regards

Chris

sisso

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 1
  • Posts: 46
    • View Profile
Re: Could widgets be caching a hard reference to atlas texture?
« Reply #7 on: September 02, 2013, 09:12:53 AM »
It is simple a code that allow to iterate and modify all prefabs in editor. For example, if you want to remove all objects with Component Debug before a release build.

sisso

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 1
  • Posts: 46
    • View Profile
Re: Could widgets be caching a hard reference to atlas texture?
« Reply #8 on: September 02, 2013, 10:05:48 AM »
OK, the problem appears to affect widgets inside a prefab. I tried disable/enable the gameObject and components for UIWidget and UIRoot but without success. But the code below work in the editor:

  1. var list = GameObject.FindObjectsOfType(UIWidget);
  2. for (var c: UIWidget in list) {
  3.         if (!c.keepMaterial) {
  4.                 c.material = null;
  5.                 c.mainTexture = null;
  6.         }
  7. }

Edited:

Testing more deep it appear to not work, and UIWidget.mainTexture = null could more problems (like set atlas.material.mainTexture to null).
« Last Edit: September 02, 2013, 12:52:30 PM by sisso »

sisso

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 1
  • Posts: 46
    • View Profile
Re: Could widgets be caching a hard reference to atlas texture?
« Reply #9 on: September 02, 2013, 04:12:48 PM »
I have created a sample project to do some tests. It is a little crazy when the hd reference get stuck and when its lose.

I can always cause the problem if a create a new Widget pointing to AtlasRef that point to AtlasHd and save scene. The component enabled/disabled fix the problem. For prefabs too. But you must always execute before build, because there is some situations where old Widgets back the texture HD reference again. It works for prefab too.

So, I need to go back to my project to identify why it now works there.

I put this sample project into github https://github.com/sisso/ngui-hdsd and could be used to understand the atlas replacement or building scripts for prefabs and scenes. NGUI is not there, it is at .gitignore.

sisso

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 1
  • Posts: 46
    • View Profile
Re: Could widgets be caching a hard reference to atlas texture?
« Reply #10 on: September 03, 2013, 07:27:28 AM »
ArenMook ruined my thread by remove the mTex and mMat from UIWigets in NGUI last version (2.6.5). Now how I will debug this problem? Hehehe This is a joke.

It appear to solve the problem once all, and without any crazy process (like loop over all prefabs enabling/disabling components).

You save my day, I'm very grateful.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Could widgets be caching a hard reference to atlas texture?
« Reply #11 on: September 04, 2013, 04:44:40 AM »
:)

Like everyone else, my understanding of how Unity works grows over time as I keep using it, and sometimes this gained insight allows me to clean up my own "wtf" code.

Washington Phillips

  • Guest
Re: Could widgets be caching a hard reference to atlas texture?
« Reply #12 on: September 09, 2013, 02:43:21 PM »
Thanks for the link sisso.

According to the Find References in Scene option in my main game scene, NGUI version 2.6.5b fixes most of the lingering references, but not all. All my atlases have 1x, 2x, & 4x versions, and one in particular still has problems. Numerous UILabels & UISprites, as well as the respective dummy atlas, and even (though probably spurious) some GameObjects without NGUI widgets refer to the 4x one. The 1x version is referred to only by one UILabel, and the 2x version to nothing.

It may be that all the widgets retaining references are ones that were at one point mistakenly set to a concrete 1x/2x/4x atlas, but I can't confirm it.

sisso

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 1
  • Posts: 46
    • View Profile
Re: Could widgets be caching a hard reference to atlas texture?
« Reply #13 on: September 09, 2013, 03:04:09 PM »
I have notice, but without confirmation, that some UITexture are still pointing to original HD version. Even when I point it to null before the build. The big problem is, in my sample it works, but not in my app. So, I have switched its default texture to SD and it solve my problem :P

sisso

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 1
  • Posts: 46
    • View Profile
Re: Could widgets be caching a hard reference to atlas texture?
« Reply #14 on: September 09, 2013, 04:07:54 PM »
A important thing that I did't notice before. AtlasReplacement script must hold the reference for all loaded resources and use DontDestroyOnLoad. If not, the unity3d could clean up during a scene transiction.

I lose half day trying to figure out why one atlas sometimes simple disappear.

I will update my sample app with this.

Edited: F@!$!@, my sample was ok :P