Проблема заключается в том, что стандартная кнопка UI обрабатывает нажатия даже по прозрачным областям, что в данном случае совсем не желательно. При этом у самого компонента Button нет никаких (видимых в инспекторе) параметров, которые могли бы отвечать за то, какие области кнопки могли бы обрабатывать наведение/нажатие.
Спустя некоторое время поисков в интернете и курения документации ко мне пришло следующее, при этом довольно простое, решение:
(Сразу оговорюсь, что подобный пример есть в документации Unity, однако на данный момент его код уже помечается как устаревший, поэтому я решил его актуализировать и немного доработать)
using UnityEngine;
using UnityEngine.UI;
public class ButtonClickMask : MonoBehaviour
{
[Range(0f, 1f)] //1
public float AlphaLevel = 1f; //2
private Image bt; //3
void Start()
{
bt = gameObject.GetComponent<Image>();
bt.alphaHitTestMinimumThreshold = AlphaLevel; //4
}
}
- Атрибут, который выведет в инспекторе удобный бегунок со значениями от 0 до 1.
- Минимальное значение альфа-канала, которое должна иметь часть текстуры, на которую наведен курсор, чтобы обрабатывать нажатия.
- Компонент Image кнопки (работать нужно именно с ним, а не с Button).
- Параметр alphaHitTestMinimumThreshold как раз и отвечает за то, какой минимальный уровень прозрачности должен быть у части текстуры, чтобы она могла обработать нажатие.
Итак, скрипт готов. Теперь перейдем к настройке текстуры кнопки. Чтобы код работал и не выдавал ошибок, необходимо включить возможность чтения/записи в Import Settings текстуры. Не забудьте принять изменения, нажав Apply.
Теперь вешаем скрипт на нужную кнопку, выставляем Alpha Level на нужное значение (в моем случае — 1)…
… запускаем и радуемся, что кнопка теперь не обрабатывает нажатия по прозрачным областям!
Комментарии (8)
SteeLMinder
04.12.2019 18:46Это в принципе хорошая вещь, но использование Read/Write делает текстуру в памяти x2. А разве включение Use Sprite Mesh не делает тоже самое ?
TheGreatB Автор
04.12.2019 19:00Сейчас проверил — не делает (хотя есть вероятность, что я что-то не так настроил).
TxN
05.12.2019 07:27Есть более экономный вариант: Использовать коллайдер для отсечения нежелательных областей:
gist.github.com/TxN/344c216ecd31cca5850ea7294fd5f0a6
Да, придется нарисовать коллайдер, но зато по ресурсам проверить попадание точки в многоугольник будет гораздо менее затратно.TheGreatB Автор
05.12.2019 11:28Такой вариант тоже возможен, но на мой личный взгляд, использование коллайдеров в канвасе — довольно странная идея. Но тут уж, думаю, что кому по вкусу.
Решение же в моей статье более мобильно (требует минимум манипуляций с компонентами), а так же, насколько я понял, именно такой способ подразумевался разработчиками движка как основной для данной задачи.TxN
05.12.2019 12:40Коллайдер тоже решение не идеальное (но ничто не мешает сделать свой алгоритм, вычисляющий попадание в многоугольник, и устранить эти недостатки), но открывать текстуру для чтения (или целый атлас), тратя этим самым память, которой на мобильных устройствах не всегда много.
Плюс, этот способ позволяет делать то, что нельзя делать простым альфа-тестом — создать область реакции на клик больше самой кнопки. Или наоборот, если зачем-то надо. Опять же, для мобильных игр вещь очень полезная.
VIONICK08
Это распространяется только на обработку нажатий или на эффекты при наведении, выделении и т. д. тоже?
TheGreatB Автор
Этот параметр влияет также и на зоны наведения на кнопку (видно на последней гифке)