- Home /
Detect If Pointer Is Over Any UI Element
I've read a half dozen posts on what I think is one of the most common scenarios I can think of but I didn't not find an answer that worked (cleanly).
I have a worldspace UI because I have units that will have action buttons that pop over their head. Naturally if the button is clicked to taken an action I dont want that click going through behind the button and hitting the grid (and hence making the unit take action and try to move too).
There used to be in the beta a function: EventSystemManager.currentSystem.IsPointerOverEventSystemObject()
Which looked like it would do the trick. However it's been since removed.
I see there is a way I can manually add an event to every UI element
http://answers.unity3d.com/questions/783279/46-ui-how-to-detect-mouse-over-on-button.html
But thats is the most ridiculous overkill solution ever.
Knowing if a pointer is over a UI element in any frame should be easily detected and Im curious if I missed something during my research?
Is there some sort of generic IsPointerOverUIElement() function?
Update My next best solution is doing a raycast and checking for a UI element hit.
Answer by HarshadK · May 15, 2015 at 06:01 AM
I overlooked this and its implementation. The name is a little misleading but after chaning some behaviour in my code this works. Thanks!
You could share your findings! UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject it is.
He probably ended up using https://docs.unity3d.com/ScriptReference/UI.Selectable.OnPointerEnter.html
This URL has since changed to: https://docs.unity3d.com/ScriptReference/EventSystems.EventSystem.IsPointerOverGameObject.html
This is wrong, this is not just for UI elements. It will be true over a 3d object's collider.
Slightly more updated:
if(!UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject()) //if cursor is not over ui element... { //Do stuff }
I think their docs are confusing regarding this function. They say:
// Check if the mouse was clicked over a UI element if (EventSystem.current.IsPointerOverGameObject()) { Debug.Log("Clicked on the UI"); }
However, IsPointerOverGameObject seems to fire for any game object with a collider (which makes sense based on the name of the function). So it's not exclusive to UI. Unless I've missed something?
Answer by SkylinR · Jul 07, 2020 at 09:33 AM
You can try this code. For me it's working like a charm.
public static 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;
}
Answer by Sjonsson · Mar 24, 2019 at 11:17 PM
I did a script that you can add to every Canvas. Then you can reach the static bool MouseInputUIBlocker.BlockedByUI from anywhere to see if the mouse is over UI or not.
I know it's dirty with the static bool I only did this as a quick fix but it might help someone:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
[RequireComponent(typeof(EventTrigger))]
public class MouseInputUIBlocker : MonoBehaviour
{
public static bool BlockedByUI;
private EventTrigger eventTrigger;
private void Start()
{
eventTrigger = GetComponent<EventTrigger>();
if(eventTrigger != null)
{
EventTrigger.Entry enterUIEntry = new EventTrigger.Entry();
// Pointer Enter
enterUIEntry.eventID = EventTriggerType.PointerEnter;
enterUIEntry.callback.AddListener((eventData) => { EnterUI(); });
eventTrigger.triggers.Add(enterUIEntry);
//Pointer Exit
EventTrigger.Entry exitUIEntry = new EventTrigger.Entry();
exitUIEntry.eventID = EventTriggerType.PointerExit;
exitUIEntry.callback.AddListener((eventData) => { ExitUI(); });
eventTrigger.triggers.Add(exitUIEntry);
}
}
public void EnterUI()
{
BlockedByUI = true;
}
public void ExitUI()
{
BlockedByUI = false;
}
}
Thank you for this. I needed to be able to detect when my cursor is over one canvas and not the other. This got me sorted pretty quickly after being stuck for a while. I just need to get it working with multiple canvases better
This is was incredibly helpful in my use case. I have a 'spacer' panel at the top of my HUD, and no matter what I did (including using Canvas Groups, as was suggested elsewhere) I couldn't get the Event System to ignore it. This made for a more selective script.
I've tried to implement the OnPointerExit and couldn't succeed. This helped me a lot. I'm thankful for this!
Answer by mgstauff · Jul 13, 2018 at 08:36 PM
I think a better solution is
bool noUIcontrolsInUse = EventSystem.current.currentSelectedGameObject == null;
That's because EventSystems.EventSystem.IsPointerOverGameObject
will fail when the cursor moves off of a control even while it's still controlling. e.g. when click-dragging a slider and you move off of it. (At least in Unity 2018.1)
EDIT: Read the comments below for an important limitation.
This only works if you're using the navigation system, which you might not want if you're just building a mouse-based UI.
@$$anonymous$$arconiusD$$anonymous$$$$anonymous$$ You mean the keyboard navigation option for UI? So if the navigation part is not enabled, currentSelectedGameObject will always be null?
Exactly, I tested and confirmed this. Basically if you have the "Send Navigation Events" checkbox turned off in the Event System, the currentSelectedGameObject always is null. It's not just for keyboard though, I think it's mostly intended for controllers, actually.
O$$anonymous$$ thanks a bunch - that's great to know.
Thank you. This is indeed better (at least for me), fixed a bug I was having
Answer by DarkJune · Dec 29, 2021 at 04:26 AM
You can add Event Trigger component to your Canvas, and add actions OnPointerEnter & OnPointerExit. After that, made new method like this:
[SerializeField]
private bool OnUI;
public void OnPointerState(bool newState) { OnUI = newState; } // Recomendation: set true when method called from OnPointerEnter action, and set false in other case.
And call this method from your actions. This way detect all moments, when you pointer is enter or exit parent UI object (in this case - your canvas) and all his childrens, that have Image component (with turned on "Raycast target" option), so rarely can be buggy. Have a good codding expirience! EDIT: This laggy when user have low framerate, in other cases - this works perfectly!
Your answer
Follow this Question
Related Questions
What does 'Event.Use()' actually do, and when to call it? 1 Answer
How to detect click outside UI panel 9 Answers
World space buttons and preventing UI touch passthrough 0 Answers
Unity UI: How to stop select event from propagating? 1 Answer
Gui.modalWindow catch mouseUp event outside of the window 0 Answers