UnityGUI click event

I’ve created a UI using UnityGUI.
When I click on either GUI.Button or GUI.Box the click is processed by objects on the scene.

if (Input.GetKeyDown ("mouse 0")) {
    Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);			
    if (Physics.Raycast (ray, out hit)) {
    // ...
    }
}

I need to determine the fact, that the UI was clicked on.
In case of GUI.Button I can check wether GUIUtility.hotControl != 0.
GUI.Box doesn’t modify GUIUtility.hotControl.

What is the common solution?

not sure what you are talking abt

–

5 Answers

5

just now i found the next solution (i use it in dragging camera routine):

		if (Input.GetMouseButtonDown(2) && GUIUtility.hotControl == 0) {
		pos = cursor.getPos(false);
		drag = true;
	}

this condition ignores mouse down when we click on gui elements

+1 for this answer. It seems if hotControl = 0 no elements of GUI are active. Thanks all.

–

Ahhh, finally i got your problem :D. To sum up:

  • You have a GUI on your screen
  • You use the above posted raycast to interact with GameObjects in your scene
  • You don’t want to interact with objects that are behind the GUI when you click on the GUI.

I think that’s your problem, right? It’s really hard to get that out of your question.

You can simply check if the mouse is inside the Rect of your box/window. If you use GUI.Box just use the Rect you’re using to create the Box. If you use GUILayout you can use GUILayoutUtility.GetLastRect to determine the Rect. To check if you are over the GUI use Rect.Contains with the mouse position (inside OnGUI use Event.current.mousePosition).

//C#
bool overGUI = false;
void OnGUI()
{
    Rect guiRect = new Rect(10,10,100,100);
    GUI.Box(guiRect);
    if(GUI.Button(new Rect(20,20,80,30),"Click Me"))
    {
        // clicked
    }
    if (Event.current != null && Event.current.isMouse)
    {
        overGUI = guiRect.Contains(Event.current.mousePosition);
    }
}

or with GUILayout

bool overGUI = false;
void OnGUI()
{
    GUILayout.BeginVertical("", "Box"); // style it like a Box
    if(GUILayout.Button("Click Me"))
    {
        // clicked
    }
    GUILayout.EndVertical();
    Rect guiRect = GUILayoutUtility.GetLastRect();
    if (Event.current != null && Event.current.isMouse)
    {
        overGUI = guiRect.Contains(Event.current.mousePosition);
    }
}

Now you can check the boolean if your over the GUI or not :wink:

ps. I wrote that from scratch so it’s not checked for syntax errors :wink:

You are absolutely correct with the definition of the problem. Thank you. Your solution is pretty obvious and it doesn't seem to be applicable in a couple of cases including mine: 1) I have serveral boxes. Iterate over a collection of Rects? Hmmm. 2) My boxes are not rectangular. They have alpha-images as background.

–

Well, from Unity's view all GUI elements are rectangular. Custom shapes are a bit tricky. The only way (if that is important) to get a perfect result is to use a Meshcollider with the shape of your GUI and raycast against it ;). If rectangles are ok you can turn your "boxes" into windows. As far as i know windows work with GetNameOfFocusedControl. Maybe the box works as well, i never tried it ;) http://unity3d.com/support/documentation/ScriptReference/GUI.GetNameOfFocusedControl.html

–

Spelling error: "Event.current.mousePosition"

–

Check this: http://answers.unity3d.com/questions/1272597/cant-get-euler-condition-to-work.html#comment-1272734

–

This is what worked for me. It ignores the first and all clicks in a GUI.textField, and sees even the very first click outside of one:

if(Input.GetMouseButtonDown(0) && GUI.GetNameOfFocusedControl()=="") {...}
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Turns out the rule about not using GUI stuff except in OnGUI doesn’t apply to getNoFC. It can be examined from Update. You have to be sure to set names – ex: GUI.SetNextControlName("b"); – in front of all your focusable controls (you can be lazy and give them all the same name.)

thanks. only solution that worked for me.

–

I've read hotcontrol and focusedcontrol solutions to this problem countless times but this is the first time I've seen a mention of being able to name your own controls X_X Documentation needs a REHAUL. edit: Well turns out that is in the documentation for GetNameOfFocusedControl, just that I hadn't visited that page of the docs yet. Not negating the fact that the docs need work, just that I spoke too soon this time

–

Ok I know what is the issue. I used: Debug Debug.Log(transform.eulerAngles.x) and I found out that my x is 356 with is strange but I will try to work around that. Thanks for help!

–

I tried to use above methods and few other but couldn’t get what I really want.

I ended up making a rect for where I see the scene from and raycast through. Game just checks whether the scene rect contains mouse click as explained in here Unity - Scripting API: Rect.Contains

This works for editor GUI

public static bool LeftMouseUp()
{
    return Event.current != null && Event.current.type == EventType.MouseUp && Event.current.button == 0;
}