- Home /
How to deactivate an NGUI panel, but not hiding it.
I am trying to deactivate/activate a panel but keep it visible. All in NGUI. So basically I have a pop up menu that appears in from of the main menu. The pop-up menu has it's own buttons that have to be active, and I don't want them to interfere with the main menu buttons, which have to remain visible but inactive.
I can go and iterate trough all the buttons in the panel and set them inactive, but I can have other elements in the main menu like scroll bars, sliders etc. So is there an universal way of setting the entire panel active/inactive but still leaving it visible?
you're only concerned about disabling the buttons that are in the panel right?
Well everything that receives events. So if I have a small window popping up asking "Are you sure?" you have 2 buttons, "Yes" and "No". Everything that was on the window underneath has to be inactive: buttons, scroll bars, sliders, text fields etc.
Answer by vexe · Sep 17, 2013 at 08:58 AM
There's a couple of ways to do it:
If you want any widget in NGUI to stop reacting to events, just take out that widget's collider.
If your buttons have a UIButton script attached to them, you can use the
isEnabled
property which enables/disables the button (by enabling/disabling the collider, and updating the button's color accordingly)You can use a boolean
acceptInput
in your panel (or main menu or whatever) - when you're handling your main menu button events (or any thing that you want to make inactve) check to make sureacceptInput
is true. When you show up the popuplist, you setacceptInput
to false.
Going with the first option (for example) you could make a function that would deactivate everything in your panel, except for one thing (in this case your popup list). Something like (just an idea, I don't know about your setup):
void ActivateAllExcept(bool activate, string _except)
{
// this will get you all the colliders of all widgets under your panel - recursively
var colliders = myPanel.GetComponentsInChildren<Collider>();
foreach (var col in colliders)
if (col.gameObject.name != _except) // for this to work, names should be unique. I just used the name as an example, use whatever unique identifier you want...
col.enabled = activate;
}
In your case you would pass in false to activate
.
Thx, I was thinking there is a built in function in NGUI. I guess I'll go with the collider enable/disable. By the way, I know Unity has some problems with real-time enabling or disabling colliders. At least form an object that has a rigidbody. Anyway, I'll try to see if I get in any problems with that. Thank you.
You shouldn't face problems with colliders, you could always fallback to removing/adding the collider which I don't think you'll ever have to. Let me know how it goes...
Btw (you probably know this) use NGUITools.AddWidgetCollider
to add a collider if there was none, or reposition/re-size the existing one, if any.
Oh, you are right, the problem was with adding/removing, not enabling/disabling. Thanks a million! :)
If you're ever curious about what NGUI has to offer, just check out what's in the source code files... A lot of information there.
I just ran a quick test on enabling/disabling colliders on my panel (same code I showed you) - it works as expected, you might wanna double check...
Answer by Symyon · Sep 17, 2013 at 09:41 AM
By the way somebody (a user named Carsten`) in the Unity chat room gave me another solution. Placing a collider on top of the others that I want to block, so basically the entire screen, under the window that I want to keep active. I though maybe it will help somebody who is looking for a solution of a simllar problem.
Interesting idea. You could do that as well yea... But then you'd fall into the annoyance of having to deal with z-depth. Do do it, you'd have to create an empty game object with a collider to it, it should be positioned between your mainmenu and popuplist, with the collider size being equal to your whole main menu (you can do that by calling NGUI$$anonymous$$ath.CalculateAbsoluteWidgetBounds over your mainmenu to get the bounds, and then let your collider to have the same size of your mainmenu bounds)...
Yes, I'll have to play with the Z-depth. $$anonymous$$ore than that, having more than one atlas I have different Z-depths for different UI elements, so it's important to keep track of all of these. I'll try and see what solution works best.
I think there's some NGUI helper plugin/addon that manages depths and Zs and all that... can't recall the name though.
Answer by mkhouri · Dec 01, 2013 at 04:08 PM
I'm currently working with Unity 4.3 and NGUI 3.0.5, and put the collider in top of other colliders stopped to work for me. I'm not sure what has changed from previous versions. The collider blocks the colliders behind but also the buttons on top of the pop up collider stopped to work as well.
Why are you asking here as an answer? - Post a separate question.
As mkhouri didn't post a separate question, I'll answer here so it may help others. With the new version of NGUI, in order to get the dept to work as it should, the object that has the collider attached has to have a UIWidget component as well, or any other component/class that derives from it (like uiSprite etc). After that you can use this block screen as you like, making it in a separate panel or in the same one the other ui elements are.
Answer by DougMcFarlane · Jan 29, 2014 at 09:41 PM
Updating @vexe's answer, I created an extension method to accomplish this. Just put the following snippet anywhere in your project, and it will extend the GameObject class to include an 'EnableColliders()' method available to all GameObjects.
I didn't see where Symyon mentioned he wanted some controls still enabled, so I removed that option. His pop-up menu is a different NGUI panel I assume (like my situation, I wanted a 'pause' menu displayed over my game when the user clicks a button, with options like 'Resume' and 'Exit', but my other game inputs kept firing also.)
public static class ExtensionMethods {
public static void EnableColliders(this GameObject go, bool state) {
foreach (var collider in go.GetComponentsInChildren<Collider>()) {
collider.enabled = state;
}
}
}
In my menu code (using my custom State Machine), I enable / disable input for GameObject 'uiHud' like this:
public void StateLostFocus() {
GuiManager.uiHud.EnableColliders(false);
}
public void StateGainFocus() {
GuiManager.uiHud.EnableColliders(true);
}
Thanks for the answer Doug, how is enabling/disabling all colliders impacting performance? On mobile in particular (if that matters). Just curious. Anyway, I find the solution with one collider, over everything else I need to block, really simple and that's the one I use, but I'm really glad that this conversation gave a few good solutions for everybody that is in search for one.
I only started working on this part of my game. Running on my PC, I see no delay whatsoever. The one collider solution also sounded good to me, when I was researching, but I was worried by the z order, especially if I have three GUIs overlapping - not that I couldn't figure out a tidy fix if I needed. I love multiple solutions too, you pick the one that suits you best.
Your answer
Follow this Question
Related Questions
Setting Background using NGUI 0 Answers
ngui anchor alignment 1 Answer
Placing button at corner using NGUI 2 Answers
NGUI: Recommended way of hiding/showing multiple menu panels? 1 Answer
Cube click pop-up menu 0 Answers