IsPointerOverGameObject() & InputAction Callback

When using the IsPointerOverGameObject() within a method subscribed to an input.action.performed. I get a warning:

“Calling IsPointerOverGameObject() from within event processing (such as from InputAction callbacks) will not work as expected; it will query UI state from the last frame”

    [SerializeField] InputActionReference select;
    void OnEnable()
    {
        select.action.performed += OnSelect;
    }

    private void OnDisable()
    {
        select.action.performed -= OnSelect;
    }
    void OnSelect(InputAction.CallbackContext context)
    {
        if (EventSystem.current.IsPointerOverGameObject())
        {
            Debug.Log("Clicked on the UI"); return;
        }
     }

My use case was to prevent clickthrough when clicking over a visual element and it seems to work other than the warning… for now. Is there a solution for this warning or a work around?

It’s been a bit of a circus for me figuring out click through prevention for visual elements when using c# invoked events. (I feel like this might not be an issue if i used messages or unity events since there’s no callback and it’s more forward moving?) So is there a better method than what I’m implementing? Had a hard time finding tutorials on visual element + input system clickthrough.

1 Like

Bumping this because I’ve also just been ignoring this warning and I can’t seem to find a reasonable workaround online.

1 Like

Maybe you’re already aware. But, it is possible to put the check in Update and just reference a bool from the callbackcontext method. No warning msg, but it’s just backwards as hell and gets us back to using update for input when the whole point of the new system was to avoid update polling for input.

4 Likes
public static class EventSystemUtility
{

private static InputSystemUIInputModule s_Module;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void Init()
{
    s_Module = null;
}

public static bool IsPointerOverGUIAction()
{
    if (!EventSystem.current)
    {
        return false;
    }

    if (!s_Module)
    {
        s_Module = (InputSystemUIInputModule)EventSystem.current.currentInputModule;
    }

    return s_Module.GetLastRaycastResult(Pointer.current.deviceId).isValid;
}
}

This will function in InputAction callbacks.

1 Like

In Unity 6 EventSystem.current.IsPointerOverGameObject() is still currently my approach. I have used the static utility described in this thread with no success. The Event System call to test for over UI works well currently, I will continue to do so until I reach a point I need to fix this.

Got rid of that annoying warning with coroutine. yield return null; skips one frame, so the method should work correctly

public void Attack(Vector2 position)
{
    GameEntryPoint.Coroutines.StartCoroutine(AttackCoroutine(position));
}

private IEnumerator AttackCoroutine(Vector2 position)
{
    yield return null;
    if (!EventSystem.current.IsPointerOverGameObject())
        if (attack.Use(this, position))
            attack.SetCooldown(AttackSpeed);
}