Detecting mouse clicks in Unity UI Beta

Detecting mouse clicks in Unity UI Beta

I want my game script to detect mouse clicks everywhere on my screen, except one corner where I have a pair of buttons to control the sound and will be handled separately. To help identify this corner, I've created a soundPanel object with the Rect Transform component (available in the Unity 4 Beta 17+) and have sized/positioned it appropriately in the editor in my UI layer. 
In my game's script, I have passed in this corner object, and tried using it in the following way:
bool tap = (Input.GetMouseButtonDown(0) || Input.GetMouseButtonUp(0))
           && !soundPanel.rect.Contains(Input.mousePosition);

Clicking in the soundPanel still triggers a tap. I figured this is because the mouse position and soundPanel.Rect are not in the same coordinate space. Since the documentation on the new Unity Beta UI is a bit lacking / hard to find, I tried converting the mouse coordinates to everything I could:
if (Input.GetMouseButtonDown(0) || Input.GetMouseButtonUp(0))
    if (soundPanel.rect.Contains(Input.mousePosition)) { print("Raw"); }
    if (soundPanel.rect.Contains(camera.ScreenToViewportPoint(Input.mousePosition))) { print("ScreenToViewportPoint"); }
    if (soundPanel.rect.Contains(camera.ScreenToWorldPoint(Input.mousePosition))) { print("ScreenToWorldPoint"); }
    if (soundPanel.rect.Contains(camera.ViewportToScreenPoint(Input.mousePosition))) { print("ViewportToScreenPoint"); }
    if (soundPanel.rect.Contains(camera.ViewportToWorldPoint(Input.mousePosition))) { print("ViewportToWorldPoint"); }
    if (soundPanel.rect.Contains(camera.WorldToScreenPoint(Input.mousePosition))) { print("WorldToScreenPoint"); }
    if (soundPanel.rect.Contains(camera.WorldToViewportPoint(Input.mousePosition))) { print("WorldToViewportPoint"); }

When I click with the above code, "ScreenToViewportPoint" and "ScreenToWorldPoint" print no matter where I click, and no others trigger. I suspect I need to transform the soundPanel somehow.
Here is the Hierarchy, Scene, and Inspector. The selected rect is the soundPanel, and it is in the bottom-right of the UI Canvas:


Answer 1:

The easiest way I found to do this was as follows:

  1. Make sure to configure your canvas to use screen space based on the camera. Drag and drop your camera into the render camera property

    Canvas Inspector

  2. Detect if the rectangle contains the mouse coordinates using RectTransformUtility.RectangleContainsScreenPoint() method. Pass in your rectTransform object, the current mouse position (takes screen coordinates so raw Input.mousePosition works fine), and the main camera object.

  3. To keep the UI position in sync with the camera, update the canvas position with a line similar to the following somewhere where it will execute after the camera position has been updated:

    canvas.transform.position = new Vector3(camera.transform.position.x, camera.transform.position.y, canvas.transform.position.z);

Answer 2:

I figured out how to detect pixel coordinates on a RectTransform by using the transform property to get the center of of the rect in pixel coordinates, then use sizeDelta to get the width and height, make a rect from that, then test it against the mouse coordinates.

Vector2 topLeft = (Vector2)soundPanel.transform.position - (soundPanel.sizeDelta / 2f);
Rect soundRect = new Rect(topLeft.x, topLeft.y, soundPanel.sizeDelta.x, soundPanel.sizeDelta.y);

bool tap = (Input.GetMouseButtonDown(0) || Input.GetMouseButtonUp(0))
           && !soundRect.Contains(Input.mousePosition);

I will say, it’s not perfect. Something is still slightly off, but it’s close enough for now.