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.
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 :(
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!
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.