My game has a dropdown menu that I've implemented with a GUI.Toggle and a GUI.SelectionGrid. The toggle button determines whether or not the selection grid should be displayed.
The SelectionGrid appears over another (unrelated) group of GUI.Toggle buttons. Even though the toggle buttons are drawn first, they still steal the mouse focus when the mouse is over the selection grid.
Both components are drawn in the same OnGUI function. Actually, they're both drawn in the same function, which gets called from the OnGUI function in my script.
Here is a screenshot that demonstrates the problem:
The mouse is over the 'Foo' item in the selection grid, yet the toggle button enters its hover state and will become active if I click my mouse.
Here's the code that draws the selection grid, which is called AFTER the list of toggle buttons has been drawn:
I finally figured this out now that I've accepted the fact that you must draw GUI elements that overlap in separate scripts.
Once I realized that, there were a couple other things I needed to figure out:
Both scripts must declare a class with a name that matches the file name (even javascript)
The classes must extend MonoBehaviour
Both scripts need to declare their GUI.depth in their OnGUI function
GUI.depth is an integer
The script with the lowest depth will be drawn last and will capture the mouse input
filename: DrawMeFirst.js
class DrawMeFirst extends MonoBehaviour
{
var bottomLayerNumber : int = 10;
function OnGUI ()
{
GUI.depth = bottomLayerNumber;
drawStuffUnderneathOtherStuff();
}
function drawStuffUnderneathOtherStuff ()
{
if ( GUI.Button(Rect(0, 0, 100, 100), "I am underneath") ) {
Debug.Log("This will never get printed");
}
}
filename: DrawMeLast.js
class DrawMeLast extends MonoBehaviour
{
var topLayerGetsMouseInput : int = 1;
function OnGUI ()
{
GUI.depth = topLayerGetsMouseInput;
drawControlsYouCanClick();
}
function drawControlsYouCanClick ()
{
if ( GUI.Button(Rect(0, 0, 100, 100), "I am on top") ) {
Debug.Log("I will always get clicked");
}
}
You don’t actually have to separate your different layers into separate scripts. The real problem is just a bug in GUI.Button; it doesn’t properly honor GUIUtility.hotControl.
See more details, and a replacement button function, on this Unity Forum thread.
Sweet. That's great because my separate script for one GUI element feels pretty silly and hacky. Can't wait to try this out!
This helped me diagnose a bug where I had two buttons overlapping each other on the screen and I couldn't manage to trigger one of the buttons no matter what its depth or order in the OnGui function. (One of the buttons should have been a box as a background image, but I made it a button for debugging purposes and never changed it.)
i tried this but it won't work where do you have to set your buttons or toggle's? do i have to set them in a function callt drawControlsYouCanClick or just under it? i tried everything can you make a simple sample with 2 buttons 1 greater then the other on top of each other?
i gave my scripts the right name and tried and tried but it won't happen. its always clicking the wrong one :(
thanks in advance,
drawControlsYouCanClick() is just a fake (descriptive) name that I used for my example. In my example GUI elements that are drawn by the function 'drawControlsYouCanClick' will be drawn on top of GUI elements that are drawn by the function 'drawStuffUnderneathOtherStuff'. I'll change my example code to make it more demonstrative...
well if I use your code (your forget the brackets of your class) I can't see any buttons. So I placed them out of the class but now it doesn't work because both buttons are hoverd. So what am I doing wrong...? Why can't I see the buttons when they are in the class? thanks for helping me out :)
Make sure that you're dragging your classes onto a GameObject that is actually enabled and part of your scene. Other than that it's pretty hard to tell if I can't see your code.
i used the code above with that same buttons for a simple try out. i always do that before i set it into my real project so with that code above it has to work right? I attached the scripts to a box in my scene and my camera has a GUI Layer so thats not the problem. I can see GUI elements but not the ones in the classes. Did you test your code or? can you test it for me? would be very helpfull i can't get it to work and I really do need those elements on top. Thanks
It seems this is appropriate topic so I’ll leave it here. GUI.Button is not broken - but if you do something like this in your script “useGUILayout = false;” it may seems so.
I just spent 5 hours debugging this problem that appeared from “nowhere”.
Imagine two buttons written in 2 scripts overlapping each other.
Script1
button1
Script2
button2
To set which one will be on top of the other you only need to set execution order in the inspector. Let’s say the execution order is first Script1 then Script2. Now if you click on the button1 which is in foreground the button1 will execute.
Here comes the nasty “useGUILayout = false”. If you wrote that line of code, say in Script 1, the rendering order would be the same but instead of executing button1 you will end up executing button2!
"only need to set execution order in the inspector" this is a thing you can do? where? not obvious... but i'd find it enormously useful
Just click on a script in Unity and above the script preview you will see an icon that says "Execution order". And btw. it seems that if you instantiate a prefab with some script the execution order will have no effect. So it only works with scripts attached to objects that were created manually. I hope you get it. :)
JorobusLab, I strongly recommend you not to use old unity GUI system because it is pure crap. I switched to GUI that I created with an orto camera, quads with colliders... - much much better, faster, reliable. You will feel a lot of pain if you continue to use that disaster of a GUI. ;)
In my case i have a clickable darkness (fullscreen background) and button submit (foreground) in one OnGUI method. And if you want to prevent darkness click when you click on submit button you may use workaround bellow.
Sweet. That's great because my separate script for one GUI element feels pretty silly and hacky. Can't wait to try this out!
– jahroyI believe this is inaccurate, GUI.depth refers to complete OnGUI of a script. Setting it multiple times inside the same OnGUI would lose the effect.
– GruThis helped me diagnose a bug where I had two buttons overlapping each other on the screen and I couldn't manage to trigger one of the buttons no matter what its depth or order in the OnGui function. (One of the buttons should have been a box as a background image, but I made it a button for debugging purposes and never changed it.)
– JPLKit