簡體   English   中英

Unity3D:檢測鼠標是否點擊了 UI 元素?

[英]Unity3D: Detect if mouse has clicked on a UI element?

這是一個非常簡單的問題,但在我在 inte.net 上找到的最新版本答案中,Unity 似乎發生了一些變化,不再有效,所以這里什么也沒有:

我得到了一些 UI 元素和一個“InputController”class,它旨在處理游戲期間的用戶輸入(控制器上的輸入通過 onclick 事件處理)。

我正在尋找的是一種能夠知道鼠標是否正在單擊 UI 元素以阻止執行我的輸入處理的方法(並避免用戶單擊“暫停”,同時游戲執行“左鍵單擊”。 “

現在,我喜歡的大多數解決方案都有些混亂或使用了 EventSystem.current.IsPointerOverGameObject()(比如這個,在寫這個問題時顯示),在 2019.4 中不再出現。 那么,有任何新的方法可以做到這一點,我是否必須制定一些 hacky 解決方案來從 UI 接收事件,然后阻止我的代碼的執行,或者我在這里遺漏了什么?

您應該研究 IPointerEnterHandler 和 IPointerExitHandler 之類的接口。 如果為 UI 元素實現這些接口,則可以將必要的代碼添加到這些接口所需的 OnPointerEnter 和 OnPointerExit 方法中。

它應該像向 InputController 添加 bool 一樣簡單,例如isInputEnabled並且僅在為 true 時處理輸入。 將其設置為 false OnPointerEnter 和 true OnPointerExit。

我也花了很多時間試圖弄清楚這一點。 我在 Unity 2022.1 上使用輸入系統和 UI 工具包(UI 元素)

以下內容應該可以幫助其他正在為此苦苦掙扎的人獲得他們需要的行為。

檢查您的 UI 文檔

您不希望您的 UI 文檔總是報告點擊次數。 因此,您需要相應地在 UXML 文檔中設置picking mode 看看下面的圖片,

全區 預定區域

在左圖中,我有一個包裝元素,它允許我 position 文檔底部的面板。 默認情況下,此元素將接收所有指針事件 我真正想要的是只接收右圖中橙色區域內的指針事件。

我可以通過將所有父元素的picking mode設置為ignore來解決這個問題:

在此處輸入圖像描述

設置輸入系統

設置新的輸入系統本身就是一個主題。 有關更多信息,請參閱文檔,但在圖像中您可以看到我使用一個簡單的按鈕事件作為單擊/點擊操作:

在此處輸入圖像描述

設置腳本

接下來您需要響應輸入操作並檢查您的輸入是否被 UI 看到

public class SimpleInput : MonoBehaviour
{
    public Camera ViewCamera;
    private PlayerControls _controls;

    private void OnEnable()
    {
        Assert.IsNotNull(ViewCamera, "ViewCamera cannot be null");

        // This class will vary depending on the name of your Input Action Asset
        _controls = new PlayerControls();
        _controls.Enable();
        _controls.Gameplay.TapAction.performed += OnInputTapAction;
    }

    private void OnInputTapAction(InputAction.CallbackContext obj)
    {
        Vector2 position = Pointer.current.position.ReadValue();
        Ray ray = ViewCamera.ScreenPointToRay(position);

        if (PointerIsUIHit(position))
        {
            Debug.Log("Ui event received");
        }
        else
        {
            // Perform game-world events here
        }
    }

    private bool PointerIsUIHit(Vector2 position)
    {
        PointerEventData pointer = new PointerEventData(EventSystem.current);
        pointer.position = position;
        List<RaycastResult> raycastResults = new List<RaycastResult>();

        // UI Elements must have `picking mode` set to `position` to be hit
        EventSystem.current.RaycastAll(pointer, raycastResults);

        if (raycastResults.Count > 0)
        {
            foreach (RaycastResult result in raycastResults)
            {
                if (result.distance == 0 && result.isValid)
                {
                    return true;
                }
            }
        }

        return false;
    }
}

輔助方法PointerIsUIHit的靈感來自Unity 論壇中的一次對話,該對話對如何完成此操作有一些見解。 它還揭示了作為 Unity Dev 的令人沮喪的經歷。

希望這可以幫助其他努力尋找合適指南的人。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM