If I have a button over my 3d world, how can I detect if a mouseClick was in the world or not?

#NOTE

This QA is extremely out of date. Regarding this annoying disaster in Unity, for 2015…


My game is a 3d world. From time to time I want to display buttons ontop of the 3d world. How can I detect mosueclicks in the 3D world? If I use Input.GetMouseDown(), I also react on buttonclicks, which I don't want.

GUI receives mouse events one frame before Input does - you can use this fact to detect whether or not a mouse event was consumed by GUI when you're checking for mouse events in Input.

if (!GUIDidConsumeMouseDown (0) && Input.GetMouseDown (0))
{
    Debug.Log ("Click in the 3D world");
}

And the pseudocode logic to detect GUI event consumption:

  • OnGUI:
  • GUIDidGetMouseDown (Event.button) = Event.current.Type == EventType.MouseDown;
  • // The rest of your GUI //
  • GUIDidConsumeMouseDown (Event.button) = Event.current.Type == EventType.Used ? GUIDidGetMouseDown (Event.button) : false;

MonoBehaviour.OnMouseDown and friends automatically handles this - if you only rely on this functionality, you do not need to track GUI event consumption.

Hi, been reading through some other postings and gathered some interesting things together that may help some other people reading this and needing a more complex solution for different reasons and using a window below the GUI.

// Boolean for when mouse is over window

var onMouseOverMenu : boolean = true;

// Creation point of window

var windowRect : Rect = Rect (20, 20, 200, 300);

// Rect of window. Can also be windowRect if the creation point is not needed anymore
// after the creation of the window

var windowRectBox : Rect;

function Update(){

//if you have multiple GUIs you could use something like:
// //Dont forget to change onMouseOverMenu to a boolean Array and to refer to this script.
// var isOnMouseOverMenu : boolean = false;
// for (var oMOMPtr : int in onMouseOverMenu)
//    if(onMouseOverMenu[oMOMPtr]==true)isOnMouseOverMenu = true;
// if(isOnMouseOverMenu){
// //... enter script here
// }

if (onMouseOverMenu) {
    // ... enter script here
}   

if (!onMouseOverMenu) {
    // ... enter script here
}   

}

function OnGUI () { windowRectBox = GUI.Window (0, windowRect, WindowFunction, "My Window"); }

function WindowFunction (windowID : int) { // Draw any Controls inside the window here

// Sets a Rect to the size of this window.
var curBox : Rect = Rect(0,0,windowRectBox.width,windowRectBox.height);

// Checks if the mouse is inside of this Rect.
// Due to a Window setting the Event.current.mousePosition to the position refering
//to this window, our Rect starts at 0,0 and not at the creation point of this window.
// Using Input.mousePosition is also a problem due to the creation of a GUI Element being
// refered to from a corner point of the screen (default top left), even if created with
// a Rect and that a Rect or Input always starts from the bottom left corner.
// So if using xyzRect.contains(Input.mousePosition){} and creating a window at xyzRect,
// you will notice that that the xyzRect.contains is not the same position as the window
// created in xyzRect, even thou these are the same Objects. For this to work,
// you would have to create all GUI elements from the bottom left corner.
if(curBox.Contains(Event.current.mousePosition)){
    Debug.Log("Mouse in Menu at " + Event.current.mousePosition);
    onMouseOverMenu = true;
} else if (onMouseOverMenu == true) {
    onMouseOverMenu = false;
}

// ... enter GUI here

}

e.g. if you have an onScreenDisplay wanting to show the distance to an object inside this screen: // place in Update()

//Where the mouse clicks
var ray = Camera.main.ScreenPointToRay (Input.mousePosition);

if (onMouseOverMenu) {
    // ... enter script here
    // ... only cast on gameObjects behind this window (or Rect)

        //Do a raycast from camera in direction of ray,
        //with a distance 100.0 and return hit.
    if (Physics.Raycast (ray, hit, 100.0)) {
        //hit.distance is the distance to the first collider.
        distanceToGround = hit.distance;
        //This draws a line, that shows the ray, in the editor.
        Debug.DrawLine (ray.origin, hit.point);
    }   
}

Use OnMouseDown() function in a script hanging on your GameObjects.

use events such as mouse position and click count inside GUI button

var gu : GUIText; var aa = 0 ; var aaa : String;

function OnGUI(){

var e : Event = Event.current;
Debug.Log(e.mousePosition);

if(aa==1){

    GUI.Button(Rect(20,100,50,50),aaa);
}

if(GUI.Button(Rect(20,30,100,50),"Button")){

     if(e.mousePosition.x <= 120){

        var ee : int = e.clickCount;        
        var eee : String = ee.ToString();

            aaa = eee;      
            print(eee);
            aa =1;

            gu.guiText.text = eee;

     }

}

}

Use GUIUtility.hotControl.