Tasharen Entertainment Forum

Support => NGUI 3 Support => Topic started by: FizzPow on February 15, 2013, 05:31:54 PM

Title: Losing sprite references using Atlas reference
Post by: FizzPow on February 15, 2013, 05:31:54 PM
I have written an editor script to set all my Atlas References to null before building to devices to ensure that it won't load the wrong atlas that I had set in the editor, then switch to the right one.  If I don't do this, my app will crash on some lower memory devices, and of course takes longer to load on others.

The problem is, that if the atlas reference is set to null, any sprites pointing to that atlas reference can lose their sprite setting in the editor if I am not super careful.  This is quite troubling when you have 100 objects that all lost their sprites and have to go reset them each to what they are supposed to be, if I didn't have a recent .scene backup.  I have had to do this many times now.  Is there anything I am doing wrong or possibly a patch that would make NGUI not reset the sprite reference even when the atlas reference is null?

Much appreciate some help on this, as it's driving me nuts.  ;D
Title: Re: Losing sprite references using Atlas reference
Post by: FizzPow on February 15, 2013, 05:43:57 PM
To add to this, even more troubling observation:

If I set an Atlas Reference to null at run-time, then load it back up later, I lose my sprite references as well.  So is there any way to properly load/unload Atlas references without causing this issue? Or some fix I could implement?
Title: Re: Losing sprite references using Atlas reference
Post by: ArenMook on February 16, 2013, 02:03:09 AM
There is no reason why you would lose sprite references. Sprites references are always temporary, and only sprite names and atlas references actually get saved. I'm curious about your choice of wording: "Atlas References". There should be only one reference atlas, and all your widgets should be using it. Thus changing the atlas reference should happen only in one place -- on the reference atlas, and never on widgets themselves.

Make sure names of your sprites match exactly in all atlases as well. They are case sensitive, so "Hello World" is not the same as "hello world".
Title: Re: Losing sprite references using Atlas reference
Post by: FizzPow on February 16, 2013, 02:17:00 AM
I am not typing in any sprite names.  This is all being done in the editor, so there is no room for typos.  When this issue occurs, many of the widgets seem to default to the first sprite on the atlas. 

The reason for the term Atlas Reference(s), is because I have 4 different Reference Atlases I am using, since I cannot fit all my assets onto one atlas.  I am using references so I can at run-time switch between SD, HD, 4X.  This issue happens whether I have 1 or 10 atlases though, so that's not relevant.  I am not changing anything on the widgets themselves, but many widgets will end up defaulting to the first sprite on the sheet in certain scenarios when the Reference Atlas is set to null.

Edit: I should add that when I said sprite references earlier, I was meaning the sprite name that each widget is set to.
Title: Re: Losing sprite references using Atlas reference
Post by: Game Whiz on February 16, 2013, 06:20:32 AM
I'm now seeing this behaviour. If in a dummy atlas, atlas.replacement is set to null, all sprite references are lost. This didn't happen previously (in 2.3 it was fine).
Title: Re: Losing sprite references using Atlas reference
Post by: Game Whiz on February 16, 2013, 07:03:44 AM
It's a bug in this latest version of NGUI. I corrected it by commenting out the line that sets the sprite name to null, if the sprite is null, in UISprite.cs:

public UIAtlas.Sprite sprite
   {
      get
      {
         if (!mSpriteSet) mSprite = null;

         if (mSprite == null && mAtlas != null)
         {
            if (!string.IsNullOrEmpty(mSpriteName))
            {
               sprite = mAtlas.GetSprite(mSpriteName);
            }

            if (mSprite == null && mAtlas.spriteList.Count > 0)
            {
               sprite = mAtlas.spriteList[0];
               mSpriteName = mSprite.name;
            }

            // If the sprite has been set, update the material
            if (mSprite != null) material = mAtlas.spriteMaterial;
         }
         return mSprite;
      }
      set
      {
         mChanged = true;
         mSprite = value;
         mSpriteSet = true;

         if (mSprite != null)
         {
            mSpriteName = mSprite.name;

            if (mAtlas != null)
            {
               material = mAtlas.spriteMaterial;
               UpdateUVs(true);
            }
         }
         else
         {               
            //mSpriteName = "";
            material = null;
         }
      }
   }
Title: Re: Losing sprite references using Atlas reference
Post by: FizzPow on February 16, 2013, 01:42:34 PM
Hmm, this is causing exception errors for me, and also still losing sprite names in some scenarios.
Title: Re: Losing sprite references using Atlas reference
Post by: Game Whiz on February 16, 2013, 01:49:12 PM
Without knowing the exceptions and the scenarios it's hard for me to offer any ideas :)

Anyway, this was a quick hack, after 15m debugging. It's working in a stock version of 2.33b. I had to redo one of my atlases, but everything is ok now.
Title: Re: Losing sprite references using Atlas reference
Post by: FizzPow on February 16, 2013, 01:55:51 PM
I am guessing I need to create a repro project to share when I have some time later.  It feels like there are about 100 scenarios where things still break for me.  That exception error happens on the get {} when the atlas is set to null.  I get one for every active sprite.
Title: Re: Losing sprite references using Atlas reference
Post by: ArenMook on February 16, 2013, 01:58:20 PM
I pushed 2.3.3c with the fix Game Whiz posted.
Title: Re: Losing sprite references using Atlas reference
Post by: FizzPow on February 16, 2013, 01:59:10 PM
I pushed 2.3.3c with the fix Game Whiz posted.

Did you do anything else? Because that's definitely not a fix as I mentioned and causes lots of exception errors?
Title: Re: Losing sprite references using Atlas reference
Post by: Game Whiz on February 16, 2013, 02:00:05 PM
Try moving your atlas switching code up in the scripting order. That way you'll have an atlas whenever you're trying to get a sprite.
Title: Re: Losing sprite references using Atlas reference
Post by: ArenMook on February 16, 2013, 02:00:59 PM
Alright well I have to run out. Please debug it properly and post a proper fix that will cause your issues to go away because I can't debug things that don't cause any issues for me. I'll check again in a few hours and put up whatever fix you come up with.
Title: Re: Losing sprite references using Atlas reference
Post by: FizzPow on February 16, 2013, 02:02:11 PM
Alright well I have to run out. Please debug it properly and post a proper fix that will cause your issues to go away because I can't debug things that don't cause any issues for me. I'll check again in a few hours and put up whatever fix you come up with.

I honestly am not sure how to fix it  =)  That's why I am posting here.  I can send you a repro project though?
Title: Re: Losing sprite references using Atlas reference
Post by: FizzPow on February 16, 2013, 02:06:19 PM
Try moving your atlas switching code up in the scripting order. That way you'll have an atlas whenever you're trying to get a sprite.

I can't have the references set to anything otherwise Unity will try to load whatever reference was set in the editor first, and then even with script execution at top, it will then re-load a different atlas at run-time.  This breaks on low memory devices that try to load HD assets and crash from out of memory.  One super lame fix =) is to always set my atlases to the lowest quality in the editor, but then it would be wasting time loading low quality assets then re-loading the proper ones.

Also there are some atlases I don't want to load at all until they are needed and then unload them, which causes all kinds of issues as well with sprites pointing to a null reference atlas as stated earlier.
Title: Re: Losing sprite references using Atlas reference
Post by: Game Whiz on February 16, 2013, 02:28:24 PM
Like I said, I have my atlases pointing to null with no problem whatsoever. To avoid having Unity loading up the last atlas in the editor, I have a "Force null" flag in my atlas manager, that I set prior to building. I run the game once in the editor, so that all atlases are set to null and then I clear that flag from my atlas manager. Then, at runtime, my atlas manager chooses the appropriate atlases.
Title: Re: Losing sprite references using Atlas reference
Post by: FizzPow on February 16, 2013, 02:31:20 PM
Like I said, I have my atlases pointing to null with no problem whatsoever. To avoid having Unity loading up the last atlas in the editor, I have a "Force null" flag in my atlas manager, that I set prior to building. I run the game once in the editor, so that all atlases are set to null and then I clear that flag from my atlas manager. Then, at runtime, my atlas manager chooses the appropriate atlases.

Well I am having all kinds of trouble, so I don't know why it works for you.  I am pulling my hair out here because I am constantly losing my sprite names and not even realizing it until I go to send out a test build and some panel I haven't even looked at in a week is all using the first sprite in the atlas.  I have been trying to debug and fix the sprite code but having no luck myself.  I will make a repro project later when I have more time.  It's extremely simple to cause this problem so I don't know why noone else is seeing this.  I want to cry, lol.
Title: Re: Losing sprite references using Atlas reference
Post by: SkaiCloud on February 16, 2013, 03:41:56 PM
I just now found out that if my atlas aren't even I loose sprite reference.
Title: Re: Losing sprite references using Atlas reference
Post by: ArenMook on February 16, 2013, 09:22:28 PM
Try 2.3.3d.
Title: Re: Losing sprite references using Atlas reference
Post by: FizzPow on February 17, 2013, 01:13:01 AM
Try 2.3.3d.

Using this latest version.  If I just simply hit delete on the atlas on my reference I get below crash and one of my sprites loses its spritename to the first sprite on the atlas.  If I set it null with my editor code, I get the same crash on all my sprites and they all lose their spritenames.

  1. NullReferenceException: Object reference not set to an instance of an object
  2. UISprite.GetAtlasSprite () (at Assets/NGUI/Scripts/UI/UISprite.cs:129)
  3. UISprite.get_isValid () (at Assets/NGUI/Scripts/UI/UISprite.cs:162)
  4. UISprite.set_spriteName (System.String value) (at Assets/NGUI/Scripts/UI/UISprite.cs:110)
  5. UISprite.set_atlas (.UIAtlas value) (at Assets/NGUI/Scripts/UI/UISprite.cs:74)
  6. UIAtlas.MarkAsDirty () (at Assets/NGUI/Scripts/UI/UIAtlas.cs:388)
  7. UIAtlas.set_replacement (.UIAtlas value) (at Assets/NGUI/Scripts/UI/UIAtlas.cs:240)
  8. UIAtlasInspector.OnSelectAtlas (UnityEngine.MonoBehaviour obj) (at Assets/NGUI/Scripts/Editor/UIAtlasInspector.cs:76)
  9. ComponentSelector.Draw[UIAtlas] (System.String buttonName, .UIAtlas obj, .OnSelectionCallback cb, UnityEngine.GUILayoutOption[] options) (at Assets/NGUI/Scripts/Editor/ComponentSelector.cs:45)
  10. ComponentSelector.Draw[UIAtlas] (.UIAtlas obj, .OnSelectionCallback cb, UnityEngine.GUILayoutOption[] options) (at Assets/NGUI/Scripts/Editor/ComponentSelector.cs:54)
  11. UIAtlasInspector.OnInspectorGUI () (at Assets/NGUI/Scripts/Editor/UIAtlasInspector.cs:116)
  12. UnityEditor.InspectorWindow.DrawEditors (Boolean isRepaintEvent, UnityEditor.Editor[] editors, Boolean eyeDropperDirty) (at C:/BuildAgent/work/14194e8ce88cdf47/Editor/Mono/Inspector/InspectorWindow.cs:888)
  13. UnityEditor.InspectorWindow.OnGUI () (at C:/BuildAgent/work/14194e8ce88cdf47/Editor/Mono/Inspector/InspectorWindow.cs:243)
  14. System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture)
Title: Re: Losing sprite references using Atlas reference
Post by: ArenMook on February 17, 2013, 05:09:42 AM
If that's the case, then somehow mAtlas.spriteList[0] ends up being null for you. How that's possible -- I can't even imagine. Add a null check to mSpriteName = mSprite.name; (line 129 of UISprite). I have no idea what is going on there in your project, and I can't reproduce it here.
Title: Re: Losing sprite references using Atlas reference
Post by: Game Whiz on February 17, 2013, 07:13:07 AM
2.33d is working perfectly for me. Thanks for also including the fix for UIWidget's finalAlpha.
Title: Re: Losing sprite references using Atlas reference
Post by: FizzPow on February 17, 2013, 01:07:03 PM
If that's the case, then somehow mAtlas.spriteList[0] ends up being null for you. How that's possible -- I can't even imagine. Add a null check to mSpriteName = mSprite.name; (line 129 of UISprite). I have no idea what is going on there in your project, and I can't reproduce it here.

Yay, I always seem to have a knack for finding issues noone else has ;)  So I added a null check and that fixes the crash, but all my spritenames are still being messed up when I remove the atlas from the reference atlas.  What can I do to help you, help me?  I will start working on a repro project?

Edit: not sure if this matters, but all my atlases are created with Texture Packer.  Could this be related?
Title: Re: Losing sprite references using Atlas reference
Post by: FizzPow on February 17, 2013, 01:42:14 PM
Ok here is a repro project as simple as I could make.  Just click the #1 sprite to toggle the reference and you will see they all switch from 1, 2, 3, 4 to 1, 1, 1, 1

Note: I am using Unity 3.5.7f6

Edit: You can also accomplish the same thing in the editor by just deleting the atlas on the reference and then setting it back again.
Title: Re: Losing sprite references using Atlas reference
Post by: ArenMook on February 17, 2013, 07:05:48 PM
You just posted NGUI's source code in public. Smart.
Title: Re: Losing sprite references using Atlas reference
Post by: FizzPow on August 06, 2013, 03:58:13 PM
I didn't get a chance to reply to this at the time, but seeing as there have been so many views.  This was fixed a couple days later, but I don't recall which version exactly at the time it was.