I have a simple script called InputManager and (for now) all it does is just to detect whether the mouse is over UI elements or not, just to prevent unwanted behaviors in the game.
void Update()
{
if (EventSystem.current.IsPointerOverGameObject())
{
Debug.Log("Its over UI elements");
}
else
{
Debug.Log("Its NOT over UI elements");
}
}
The problem is that the message “Its over UI elements” always shows up in the console, I turned off the canvas just to see if there is something messing with this function but nothing happened, apparently a lot of devs are suffering from the same issue.
I’ve used this which works well - comes from an old forum post.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class UITest : MonoBehaviour
{
int UILayer;
private void Start()
{
UILayer = LayerMask.NameToLayer("UI");
}
private void Update()
{
print(IsPointerOverUIElement() ? "Over UI" : "Not over UI");
}
//Returns 'true' if we touched or hovering on Unity UI element.
public bool IsPointerOverUIElement()
{
return IsPointerOverUIElement(GetEventSystemRaycastResults());
}
//Returns 'true' if we touched or hovering on Unity UI element.
private bool IsPointerOverUIElement(List<RaycastResult> eventSystemRaysastResults)
{
for (int index = 0; index < eventSystemRaysastResults.Count; index++)
{
RaycastResult curRaysastResult = eventSystemRaysastResults[index];
if (curRaysastResult.gameObject.layer == UILayer)
return true;
}
return false;
}
//Gets all event system raycast results of current mouse or touch position.
static List<RaycastResult> GetEventSystemRaycastResults()
{
PointerEventData eventData = new PointerEventData(EventSystem.current);
eventData.position = Input.mousePosition;
List<RaycastResult> raysastResults = new List<RaycastResult>();
EventSystem.current.RaycastAll(eventData, raysastResults);
return raysastResults;
}
}
Hi dave thank you for your answer but I have already found the issue, the problem was is that I have 2 cameras in the scene one for the UI (UICamera) and second one is for the rest of the gameobjects (MainCamera), a PhysicsRaycaster component was attached to the MainCamera just to detect mouse/touch inputs on the gameobjects using unity pointer interfaces (IEventSystemHandler) and once I disabled that component everything went ok.
You dont need to disable the PhysicsRaycaster, just uncheck the event mask(layer mask) that you dont want it to interfere with. because you might still need to use the PhysicsRaycaster to select a 3d object, but if you disable it you wont be able to. hope this helps
It’s not often I can copy code directly from an answer and it just works. This time it did. You saved me atleast 30 minutes of looking this up and figuring it out on my own. Thank you!
public static bool IsMouseOverUi
{
get
{
// [Only works well while there is not PhysicsRaycaster on the Camera)
//EventSystem eventSystem = EventSystem.current;
//return (eventSystem != null && eventSystem.IsPointerOverGameObject());
// [Works with PhysicsRaycaster on the Camera. Requires New Input System. Assumes mouse.)
if (EventSystem.current == null)
{
return false;
}
RaycastResult lastRaycastResult = ((InputSystemUIInputModule)EventSystem.current.currentInputModule).GetLastRaycastResult(Mouse.current.deviceId);
const int uiLayer = 5;
return lastRaycastResult.gameObject != null && lastRaycastResult.gameObject.layer == uiLayer;
}
}
Not sure yet if it works reliably… but looks good so far.
I wanted to avoid shooting raycasts with every query, so I was looking for a way to access the EventSystem’s last raycast result.
If you want to know that the mouse is over a specific UI element and do a function ( eg. show a tooltip ). You can use the IPointer events on that gameobject.
EG.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
// Event System's IPointer things are very easy to work with. Though, can be a little laggy.
public class SC_TooltipShower : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
public SC_GameController gameController;
public string header = "";
[TextArea(5,10)]
public string body = "";
public string footer = "";
void Start()
{
gameController = FindObjectOfType<SC_GameController>();
if (header == null)
{
header = "";
}
if (body == null)
{
body = "";
}
if (footer == null)
{
footer = "";
}
}
public void OnPointerEnter(PointerEventData eventData)
{
gameController.tooltipHandler.ShowTooltip(body, header, footer);
}
public void OnPointerExit(PointerEventData eventData)
{
gameController.tooltipHandler.Hide();
}
}
An easy way that works for me, is to first write the using statement “using UnityEngine.EventSystems;” at the top of the script attached to the UI element you want that should react to your mouse pointer.
After that, add the interfaces “IPointerEnterHandler” and “IPointerExitHandler” to the class line, like this :
“public class YourScript : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler”, this will let you use the methods “void OnPointerEnter(PointerEventData pointerEventData)”
and “void OnPointerExit(PointerEventData pointerEventData)”. Those ways will of course detect when the mouse enters that UI element’s space and when it exits it. Make sure no other UI elements are covering the element you want to interact with, they could be transparent.