Author Topic: extra UIPanel being created  (Read 5797 times)

Gillissie

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 48
    • View Profile
extra UIPanel being created
« on: August 18, 2013, 12:27:20 PM »
I've been running into a situation where when I drag a prefab of NGUI stuff into my NGUI hierarchy in the scene, it always ends up with a UIPanel on it when it shouldn't. I dug into it and found that there must be a Unity bug that temporarily puts the new scene object at the root, which is when the OnEnable of UIImageButton is fired off, THEN gets moved to the final place in the hierarchy. NGUI always thinks there is no UIPanel rendering this new thing since it checks while the object is at the root of the project. I have reported this bug to Unity, but in the meantime I have also made these changes to UIImageButton, which seems to help as well.

Basically, in the OnEnable() function, I pass false to the UpdateImage() function, telling it not to do a MakePixelPerfect(), since that is what triggers creating the UIPanel. I don't think it's necessary to call MakePixelPerfect() during OnEnable() anyway.

  1.         void OnEnable () { UpdateImage(false); }        // Gillissie added false argument.
  2.        
  3.         void UpdateImage(bool makePixelPerfect = true)  // Gillissie added makePixelPerfect argument.
  4.         {
  5.                 if (target != null)
  6.                 {
  7.                         if (isEnabled)
  8.                         {
  9.                                 target.spriteName = UICamera.IsHighlighted(gameObject) ? hoverSprite : normalSprite;
  10.                         }
  11.                         else
  12.                         {
  13.                                 target.spriteName = disabledSprite;
  14.                         }
  15.                         if (makePixelPerfect)
  16.                         {
  17.                                 // Gillissie - Added this condition, since calling this when dragging a prefab
  18.                                 // into the scene in the editor causes a UIPanel to be added unnecessarily,
  19.                                 // due to a bug in Unity where the OnEnable() function is called on objects
  20.                                 // before they reach their final place in the hierarchy, so NGUI doesn't find
  21.                                 // the UIPanel when first being activated.
  22.                                 target.MakePixelPerfect();
  23.                         }
  24.                 }
  25.         }
  26.  

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: extra UIPanel being created
« Reply #1 on: August 18, 2013, 02:57:54 PM »
Hmm. It should assume the correct sprite when it's enabled, and if it assumes the sprite then it should also make sure that it's pixel-perfect. Better question is why is calling MakePixelPerfect causing the panel to get added?

Panels get added in order to *draw* the widget(s). Nothing can be drawn without a panel being present. As long as you add the widget(s) underneath your UI hierarchy, no new panels will be added.

Gillissie

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 48
    • View Profile
Re: extra UIPanel being created
« Reply #2 on: August 20, 2013, 11:31:29 AM »
I'm not sure you understood the description of the original problem, which appears to be a Unity bug.

I have the "UI Root (2D)" standard NGUI hierarchy in my scene. There is a UIPanel in there that I want to drag a prefab onto. The prefab consists of NGUI elements, including sprites and UIImageButtons, but doesn't have a UIPanel at its root because I plan on using the on already in the scene's hierarchy. However, when dragging the prefab onto the existing UIPanel object, the new object (from the prefab) ends up with another UIPanel on it. After some investigation, here's what's happening.

1. The new object is instantiated at the root of the project by Unity.
2. The OnEnable() function is called in UIImageButton.
3. UIImageButton makes a call to MakePixelPerfect().
4. MakePixelPerfect looks for the rendering UIPanel for sprites on the UIImageButton.
5. Since the new object is in the root, it doesn't find a UIPanel and creates one.
6. Eventually, Unity moves the new object to the final place in the hierarchy (the object you dropped the prefab onto).
7. Now your object has a UIPanel on it even though it's under another UIPanel.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: extra UIPanel being created
« Reply #3 on: August 20, 2013, 01:40:13 PM »
Yes, I understand the issue. Generally when instantiating UI elements you will do NGUITools.AddChild, which sets the parent before doing anything else. When you drag something through the scene view, Unity will indeed attempt to draw it, which will cause functions to be called and the panel to get added. My question was why does calling make pixel perfect caused the panel to get added. It shouldn't have.

Gillissie

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 48
    • View Profile
Re: extra UIPanel being created
« Reply #4 on: August 21, 2013, 06:55:17 AM »
I guess there is more than one way NGUI can to get to adding the UIPanel under this situation, but to answer your question here is the stack trace from UISprite.MakePixelPerfect():

UIPanel:Find(Transform, Boolean) (at Assets/Code/Libraries/NGUI/Scripts/UI/UIPanel.cs:1279)
UIPanel:Find(Transform) (at Assets/Code/Libraries/NGUI/Scripts/UI/UIPanel.cs:1290)
UIWidget:CreatePanel() (at Assets/Code/Libraries/NGUI/Scripts/Internal/UIWidget.cs:348)
UIWidget:set_material(Material) (at Assets/Code/Libraries/NGUI/Scripts/Internal/UIWidget.cs:201)
UISprite:GetAtlasSprite() (at Assets/Code/Libraries/NGUI/Scripts/UI/UISprite.cs:343)
UISprite:get_isValid() (at Assets/Code/Libraries/NGUI/Scripts/UI/UISprite.cs:155)
UISprite:MakePixelPerfect() (at Assets/Code/Libraries/NGUI/Scripts/UI/UISprite.cs:414)

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: extra UIPanel being created
« Reply #5 on: August 21, 2013, 10:07:06 AM »
That does help, thanks. I'll have it fixed.