Author Topic: Using NGUItools.SetActive to hide and unhide buttons breaks their functionality.  (Read 7398 times)

LionusPrime

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 7
    • View Profile
Hi,

I'm trying to hide and unhide context-sensitive functionality based on what the player has selected.
The logic is working correctly to identify the selections as my debug.logs are going off when expected. Also, the buttons are hiding and unhiding, but when they are hidden through any way (disabling in unity editor with the checkbox, disabling with NGUItools.setactive) and re-enabled, they reappear visually, but no longer respond to mouseovers or clicks etc.

The code I'm using is here:

  1. // First check if the list is empty. If it is, we want no context sensitive commands to appear at all.
  2.                 if (_selection.Count <= 0)
  3.                 {
  4.                         NGUITools.SetActive(MoveOrderButton,false);
  5.                         NGUITools.SetActive(AttackOrderButton,false);
  6.                         return;
  7.                 }
  8.                 // Check what is selected.
  9.                 foreach (GameObject g in _selection)
  10.                 {
  11.                         if (g.tag == "Units")
  12.                         {
  13.                                 Debug.Log("Selection is units.");
  14.                                 // Set up the appropriate Order buttons.
  15.                                 NGUITools.SetActive(MoveOrderButton,true);
  16.                                 NGUITools.SetActive(AttackOrderButton,true);
  17.                         }
  18.                 }

The button just completely ceases to function, but if I start the game with them enabled, they work until they have been disabled and re-enabled at least once. MoveOrderButton and AttackOrderButton are the gameobjects that have the UISprite, UIButton and BoxCollider components on them that make them functional as a button until disabled and re-enabled.

Edit:

List of things I have checked:

None of the script components or the collider get/remain disabled when re-activating.
« Last Edit: July 23, 2014, 12:09:38 PM by LionusPrime »

LionusPrime

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 7
    • View Profile
Ok, that actually wasn't the issue. I had another sprite representing the background of that UI element that I stuck a collider on to stop the player clicking through it. For some reason, despite maintaining visual depth, when re-enabled after a disable, the buttons colliders are somehow being obscured by the background's one, as when I disabled that, the buttons worked.

Anyone know why that's happening, and know a workaround that doesn't involve losing my entire taskbar background? Haha :)

Edit:

I have fiddled with depths a lot, that did nothing and it is now definitely set up correctly for depth and it is still occurring. I think disabling and re-enabling the gameobject forces a recalc of where it is in Unity's hierarchy, and that causes the colliders (which are, in unity terms, in the same Z coordinate for the 2D interface according to the inspector) to have different priorities and block each other incorrectly. I've got a *disgusting* hacky workaround in place - whenever any button is unhidden, I hide then immediately unhide the background sprite straight after to force it to the back of whatever collider hierarchy I'm running foul of. I'd really appreciate any input on why this is happening and the best way to fix it though...
« Last Edit: July 23, 2014, 02:32:44 PM by LionusPrime »

ryan

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 1
  • Posts: 90
    • View Profile
UICamera is doing a RaycastAll for hit detection, so overlapping colliders shouldn't affect anything there.  But if you've got a collider on an object that doesn't itself have a UIWidget, then the logic in NGUITools.CalculateRaycastDepth may be having some issues.  Or if the colliders are under different panels and you've got some really crazy depth values on the widgets…  Take a look at that method to see if it gives you any ideas.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Raycasts in NGUI are simple. NGUI does a ray cast, hits colliders, then sorts the results by widget depth. If the collider is attached to a game object rather than a widget, then NGUI is forced to do GetComponentsInChildren<UIWidget>() on it, gathering all of its widgets, and then using the top-most one's depth. So if you slap a collider on a root game object, it will effectively obscure everything else. This is why you should be adding colliders to widgets, not game objects.

Nicki

  • Global Moderator
  • Hero Member
  • *****
  • Thank You
  • -Given: 33
  • -Receive: 141
  • Posts: 1,768
    • View Profile
If there are no Widgets directly on the background or in its child hierarchy, the panel will effectively count as being at z-depth 0 circumventing the proper depth setting, which can yield unexpected results. For good results, always attach at minimum a UIWidget to anything you want to have a collider on and be clickable, then you can also take advantage of such snazzy features as anchors, like stretching an invisible background to fullscreen and other some such.

LionusPrime

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 7
    • View Profile
Hey there, thanks for the replies.

All of the objects do have widgets on them, and I added the colliders to them via the NGUI menu options to do so.

The background does have a UISprite on it with a widget with a collider on it. Everything that is in the hierarchy has a widget of some kind on it - I even made the organisational 'empty' parts into UIPanels and sorted them in the depth hierarchy correctly so the buttons are on top of their panel, which is on top of the background, which is on top of its own panel, and the panels don't have colliders on them.

The issue only happens when disabling and re-enabling, so I think it's something to do with depth being messed around with then, hence the workaround of disabling and re-enabling the background - sending it to the back when re-enabled or something I guess?

So yeah, all of them have widgets and I added colliders using the option in the NGUI menu, not just slapping a box collider on it manually. Anyone have any other ideas?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Turn on Debug on the UICamera to see what's intercepting events, then post a picture of the inspector window of the object that intercepted it. That should help.

LionusPrime

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 7
    • View Profile
Ok, I've uploaded it as an attachment here. It's the background sprite intercepting when I mouse over the buttons (the placeholder white ones with arrows on in the bottom right). It's selected in the inspector.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Why is your UI under your Player Controller? 2D UI should be stationary, and generally separate from everything else. The object you have selected is quite large -- 1920x360. I'll assume it's intentional. It's also not quite clear which object it actually is. Your bottom UI seems to be made up of a bunch of different elements, and none of them account for the large 1920x360 rectangle. Do you have more than one panel in there? If you have panels, their depth is more important than widget depth. If panels share the same depth, it's not clear which one will end up on top.

LionusPrime

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 7
    • View Profile
Ah, I can move it out of the player controller. That was probably an oversight on my part.

The 1920*360 element makes up the entire background at the bottom - all the grey squares are that, and the individual other elements are the 96*96 sprites to make up the buttons (white with green arrow, white with red arrow explosions etc.). That element is the entire thing at the bottom, the gap in the middle is achieved with transparency in the texture. There are multiple panels, but none share the same depth (i.e., if I change one of their depths to a value I know is shared, the warning about depth sharing panels appears, and if I change it back, this disappears).

I'll move the UI controller out, probably just a misunderstanding on how it worked on my part, but the depth things I've scoured thoroughly and I'm fairly confident about that - the problem is that despite not changing numerically in the inspector, the depth definitely does change behaviourally, as anything I disable and then re-enable goes behind everything else. If I remove the context-sensitive disabling and re-enabling, everything works as I would expect and there are no depth issues, I am pretty sure the problem lies somewhere in the disable/re-enable process, not my depth tree, as it only becomes an issue if I disable and re-enable a button, it goes behind the background sprite, and then disabling and re-enabling the background sprite, puts it back behind the button.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
That element is the entire thing at the bottom, the gap in the middle is achieved with transparency in the texture.
Wow, really? That's a horrible waste of texture memory right there. You can achieve the same grey look using a 2x2 sprite, sliced with a 1 pixel border. Use 3 sliced sprites to form the same exact looking background -- left, middle, and right.

I see no reason for enabling/disabling objects to affect panel depth, so you can submit a repro case for me to have a look at if you like. Just please clean up it a bit so that I will have less distractions to examine when looking at the issue. The best method is to email a dropbox link to support at tasharen.com.

Nicki

  • Global Moderator
  • Hero Member
  • *****
  • Thank You
  • -Given: 33
  • -Receive: 141
  • Posts: 1,768
    • View Profile
I imagine that it's just temp graphics now and you want it to be something like what Starcraft 2 has, where the whole thing is unique, so you can't slice it up easily. Otherwise, that look could be done with a 3x3 sliced sprite and some compositing. ;)

It does sound quite strange, since there's nothing to me that sounds like it would break from that - I disable/enable things on the fly all the time. If you export a .unitypackage without NGUI in it, you can post it on here and I'll take a look too.

LionusPrime

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 7
    • View Profile
Yes, precisely - this is all placeholder template stuff to hand to a UI artist for them to paint over, and it's going to end up all looking unique.

As soon as I get around to it (had a busy few days) I'll knock up a quick repro case, shouldn't take too long, and mail it over.

Thanks :)

LionusPrime

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 7
    • View Profile
So, I fixed it, and as far as I can tell I did just do something stupid...

I had the depth sorted in the widgets and panels correctly, but the actual Z position in Unity was the same (0) for all of them. Moving the background backwards on the Z axis by one unit fixed the issue completely and caused no side effects (still looked perfect to because of ortho camera obviously)...

So, thanks very much for all your help and apologies of a thousands noobs for wasting all that time...

LOL I'M A PROGRAMMAR  :o