prevent click event on world objects when a click on ui element occurs

What Im doing: menu with options appearing at a click point
Short video: Screen capture - 1f64bddfbb0a2c99fccf4b17bdc139ce - Gyazo

I used to have a script on canvas which decides whenever its a click on classic UI or is a click on a world object:

    private void Update()
    {
        HandleClickInput();
    }

    private void HandleClickInput()
    {

        if (Input.GetMouseButtonDown(0))
        {
            Debug.Log("user click");
            eventData.position = Input.mousePosition;
            List<RaycastResult> results = new List<RaycastResult>();
            graphicRaycaster.Raycast(eventData, results);
            bool hitUIButton = false;

            foreach (RaycastResult result in results)
            {
                if (result.gameObject.tag == "UIButton")
                {
                    hitUIButton = true;
                    break;
                };
            }


            if (hitUIButton)
            {
                //DO STUFF THAN CLOSE
                Debug.Log("CLICK ON UI ELEMENT");
            }
            else
            {
                CloseMenus();
                mousePositionGlobal = Input.mousePosition;
                PositionContextMenu();
                ShowActionOptions();
            }
        }
    }

So it was raycasting through gameobjects and if clicked on any object in the world, it would trigger appearance of buttons with actions related to this object. e.g.:
-click on ground - show button with movement option
-click on unit - show button with attack or interact option
and if one of the raycast results is an UI button it was just doing whats bound to the button.

Now Im trying to achieve the same logic with UIDocument, I wrote some logic already for UXML and connected it with the above script:

public class ContextMenuUXML : MonoBehaviour
{
    private VisualElement root;
    private VisualElement contextMenu;
    private UQueryBuilder<Button> buttons;

    private void OnEnable()
    {
        UIDocument uiDoc = GetComponent<UIDocument>();
        root = uiDoc.rootVisualElement;
        contextMenu = root.Q<VisualElement>(name: "ContextMenu");
        buttons = GetAllButtons();

        RegisterButtonCallbacks();
    }

    public void PositionContainer(Vector2 mousePosition)
    {
        Debug.Log("position container ");

        contextMenu.style.top = Screen.height - mousePosition.y;
        contextMenu.style.left = mousePosition.x;
    }

    private void OnDisable()
    {
        UnregisterButtonCallbacks();
    }

    public void ShowButton(string buttonName)
    {
        Debug.Log("showing button");
        contextMenu.Q(name: buttonName).style.display = DisplayStyle.Flex;
    }

    public void HideButtons()
    {
        buttons.ForEach((Button button) =>
        {
            button.style.display = DisplayStyle.None;
        });

    }

    private void RegisterButtonCallbacks()
    {

        buttons.ForEach((Button button) =>
        {
            button.RegisterCallback<ClickEvent>(ButtonOnClick);
        });
    }
}

However i dont quite understand how to only trigger whats bound to UI button, and not trigger a world click in this case.

So the question in short:
How to prevent click event on world objects when a click on ui element occurs?

Thank you

You can use EventSystem.IsPointerOverGameObject()

1 Like

I dont think this works for UIElements (UI Toolkit), probably its for Canvas UI

I don’t know why it works for me then.

UI Toolkit is meant to work with the event system. It receives inputs from it after all.

Otherwise from memory, RegisterCallback method has overloads with an enum to specify whether the input should ‘tickle down’ or not. ‘NoTrickleDown’ should stop it from going through.

1 Like

Do you realize this has been deprecated since many years?

It’s not deprecated the code is just now in a package: https://docs.unity3d.com/Packages/com.unity.ugui@2.0/api/UnityEngine.EventSystems.EventSystem.html#UnityEngine_EventSystems_EventSystem_IsPointerOverGameObject