Unity. Использование New Input System и UI

Всем привет!

Начал делать проект в Unity. Вопрос в том как правильно обрабатывать тап по UI button на Androind?

Смысл в том что у меня есть event, который срабатывает при тапе по экрану. На сцене есть счётчик который считает тапы по экрану +1Damage (условный кликер). Рядом висит Button, эта кнопка должна отвечать за какие-то действия, например: нажимая на кнопку покупаешь какой-то баф.

Проблема в том когда тапаешь по кнопке, так же срабатывает и event тапа по экрану который добавляет +1Damage. Как определять тапнул ты по экрану или по кнопке? Пробовал метод IsPointerOverGameObject(), он вроде срабатывает, но выдаёт не критическую ошибку о том что его нужно использовать в методе Update, мне это не подходит. Можете подсказать возможные решения проблемы?


Ответы (2 шт):

Автор решения: Дмитрий Селиханович

Я решил эту проблему следующим образом:

При нажатии на экран нужно проверить попадает ли луч в точке нажатия на UI элемент. За это у меня отвечает следующая функция:

//// проверка нажатия на UI элементы
private bool IsPointerOverUIObject(){
    
    // проверка на идиота
    if( EventSystem.current == null ){
        
        Debug.LogError("ВЫ НЕ ДОБАВИЛИ EventSystem на сцену, добавте её!!!");
    }
    
    PointerEventData eventDataCurrentPosition = new PointerEventData(EventSystem.current);
    eventDataCurrentPosition.position = new Vector3(Input.mousePosition.x, Input.mousePosition.y, Input.mousePosition.z);
    
    List<RaycastResult> results = new List<RaycastResult>();
    EventSystem.current.RaycastAll(eventDataCurrentPosition, results);
        
    return results.Count > 0;
}

Функция проверяет и если нажатие произошло на UI элемент вернёт TRUE, если вернёт FALSE можно выполнять твой код +1Damage.

Когда будешь обрабатывать нажатие вызови эту функцию и проверь есть ли UI элемент ( твоя кнопка или любая другая ) в точке нажатия:

// если точка на UI элементе то не выполняем действие
if( !IsPointerOverUIObject() ){
    
    // твой код +1Damage исполнится т.к. это не UI элемент
        
}
else{
    
    // Действие не будет выполнено т.к. нажатие на UI элемент;

}
→ Ссылка
Автор решения: Yaroslav

EventSystem вообще не нужно использовать напрямую!

Подобно тому, как у тебя есть объект Button, должен быть объект для клика растянутый на весь экран, который обрабатывает реакцию на клик. Если под кликом находятся сразу несколько элементов, то обработан будет тот, кто выше в иерархии канваса, то есть тот, кто отрисовывается поверх.

Является ли объект, целью обработчики EventSystem определяет флаг RaycastTarget, который можно увидеть у Image и Text. Если у дочернего Image стоит флаг RaycastTarget, то и компоненты на родительском объекте обрабатываются, как это происходит с той-же Button, где клик на самом деле происходит по Image или Text и без них Button не работает.

Класс Button обрабатывает событие клика реализуя интерфейс IPointerClickHandler, но он срабатывает при отжатии. Если нужно события касания, то необходимо написать компонент реализующий IPointerDownHandler.

И нет нужды в никаких проверках, тот ли это ёжик и не являешься ли ты жирафом, или другая чушь, которой этот объект заниматься вообще не должен, потому что, его ответственность. Это только реакция на событие и ничего более. Кто и как это событие обрабатывает, не его собачье дело, а занимается этим тот самый EventSystem, вопросов к которому у нас быть не должно.

→ Ссылка