IsPointerOverGameObject not working with touch input

I’m using IsPointerOverGameObject() inside OnMouseDown() to detect whether the player is clicking/touching a GUI button that happens to be over the game object. If that’s the case, the function ignores the remainder of the code in OnMouseDown() by immediately returning:

void OnMouseDown()
{
    // Detect mouse event
    if (EventSystem.current.IsPointerOverGameObject())
    {
        print("return mouse");
        return;
    }
    // Detect touch event
    foreach (var touch in Input.touches)
    {
        if (EventSystem.current.IsPointerOverGameObject(touch.fingerId))
        {
            print("return touch");
            return;
        }
    }

    // Other code...

}

In the editor, this works as expected when clicking a GUI button over the game object: the function prints “return mouse” and returns. On my Android device, the GUI object is interacted with, but the OnMouseDown() function doesn’t return!

How can I fix this problem?

After some hours, I managed to find a work around:

private bool IsPointerOverUIObject() {
    PointerEventData eventDataCurrentPosition = new PointerEventData(EventSystem.current);
    eventDataCurrentPosition.position = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
    List<RaycastResult> results = new List<RaycastResult>();
    EventSystem.current.RaycastAll(eventDataCurrentPosition, results);
    return results.Count > 0;
}

Taken from this thread:

http://forum.unity3d.com/threads/ispointerovereventsystemobject-always-returns-false-on-mobile.265372/

I include that code and then just substitute EventSystem.current.IsPointerOverGameObject() with IsPointerOverUIObject() and it works.

Hope this helps someone.

from unity docs

If you use IsPointerOverGameObject() without a parameter, it points to the “left mouse button” (pointerId = -1); therefore when you use IsPointerOverGameObject for touch, you should consider passing a pointerId to it.

https://docs.unity3d.com/ScriptReference/EventSystems.EventSystem.IsPointerOverGameObject.html

you can use this code to check touch & mouse

/// <returns>true if mouse or first touch is over any event system object ( usually gui elements )</returns>
		public static bool IsPointerOverGameObject(){
			//check mouse
			if(EventSystem.current.IsPointerOverGameObject())
				return true;
			
			//check touch
			if(Input.touchCount > 0 && Input.touches[0].phase == TouchPhase.Began ){
				if(EventSystem.current.IsPointerOverGameObject(Input.touches[0].fingerId))
					return true;
			}
			
			return false;
		}

For future visitors, as far as I know, both of the solutions above generates quite a lot of garbage. Also one of them only supports single touch. So as far as I can tell, I think the solution should be something like

        public static bool IsPointerOverGameObject()
        {
            // Check mouse
            if (EventSystem.current.IsPointerOverGameObject())
            {
                return true;
            }

            // Check touches
            for (int i = 0; i < Input.touchCount; i++)
            {
                var touch = Input.GetTouch(i);
                if(touch.phase == TouchPhase.Began)
                {
                    if (EventSystem.current.IsPointerOverGameObject(touch.fingerId))
                    {
                        return true;
                    }
                }
            }
            
            return false;
        }

This workes great, thanks for the help