Как заставить невидимую прозрачную кнопку работать?

Глядя на некоторые ответы на форумах Unity и на сайте вопросов и ответов, ответы о том, как сделать невидимую кнопку, не работают, потому что удаление изображения, связанного с кнопкой, делает ее неработающей.

Как обойти это и сохранить невидимое свойство, позволяя кнопке работать?


person Ryan Cocuzzo    schedule 27.04.2016    source источник
comment
Просто удалите дочерний текст и измените альфа-канал изображения на 0.   -  person Łukasz Motyczka    schedule 27.04.2016
comment
Почему нет? Не будет ли проблем?   -  person Łukasz Motyczka    schedule 27.04.2016
comment
Короче говоря, Unity забыла, или предпочла не делать, иметь осязаемую концепцию в объектно-ориентированной цепочке для таких вещей, как изображения, которые, ну, осязаемы. По сути, это означает, что мы, разработчики, должны (так или иначе) создать собственный класс Touchable для Unity, что является классической ситуацией обратного заполнения ОО. При обратной засыпке общая проблема заключается в том, что она должна полностью автоматически поддерживаться, и, к счастью, есть одно хорошее решение.   -  person Fattie    schedule 27.04.2016
comment
@JoeBlow Я удалил свой ответ, потому что я использовал ваш ответ, и он был действительным, но для протокола: ответ, который я разместил ранее, был копией МОЕГО собственного ответа, который я считал правильным ответом.   -  person Ryan Cocuzzo    schedule 27.04.2016
comment
Между прочим, это очень важный вопрос. Примечательно, что это первый раз, когда об этом спросили на SO. Тот факт, что в Unity отсутствует осязаемая концепция, является одной из 3 или 4 странностей Unity — вы должны учитывать это в каждом отдельном проекте. Отличный вопрос.   -  person Fattie    schedule 27.04.2016


Ответы (4)


Это одна из тех странных вещей в Unity...

100% реальных проектов нуждаются в этом, но Unity забыли это сделать.

Укороченная версия:

Вам нужен Touchable.cs в каждом проекте Unity:

// file Touchable.cs
// Correctly backfills the missing Touchable concept in Unity.UI's OO chain.

using UnityEngine;
using UnityEngine.UI;
#if UNITY_EDITOR
using UnityEditor;
[CustomEditor(typeof(Touchable))]
public class Touchable_Editor : Editor
     { public override void OnInspectorGUI(){} }
#endif
public class Touchable:Text
     { protected override void Awake() { base.Awake();} }
  1. Используйте обычную функцию редактора «Создать кнопку» в Unity.

  2. Как вы знаете, функция редактора автоматически добавляет два компонента. Один Text, другой Image...

  3. Просто удалите их обоих

  4. Поместите приведенный выше скрипт Touchable.cs на кнопку.

Вы сделали. Вот и все.

Он не может «распадаться» с обновлениями Unity.

На самом деле вы можете "застегнуть" что угодно в .UI, поместив Touchable поверх него.

Никогда больше не «добавляйте прозрачное изображение», чтобы сделать кнопку.


Unity забыла абстрагировать «осязаемое» понятие в объектно-ориентированной цепочке.

Итак, мы, разработчики, должны сделать свой собственный класс Touchable «из» классов Unity.

Это классическая проблема «обратной засыпки» в объектно-ориентированном подходе.

При «обратной засыпке» единственная проблема заключается в следующем: она должна полностью автоматически поддерживаться. Есть только одно хорошее решение — Touchable.cs, которым все пользуются.


Итак, во всех реальных проектах Unity кнопка выглядит так:

введите описание изображения здесь

ONE У вас есть Button.cs от Unity

ДВА нужно добавить Touchable.cs

Некоторые команды создают функцию редактора «Создать лучшую кнопку», которая просто создает игровой объект с помощью Button.cs + Touchable.cs.

Важный совет...

Допустим, у вас может быть очень сложный пользовательский интерфейс panel. Таким образом, он изменяет размеры или даже имеет анимацию.

На самом деле, вы можете просто поместить «Button+Touchable» на что-нибудь подобное, и это сработает.

Просто установите Button+Touchable, чтобы расширить родительский элемент. Вот и все.

введите описание изображения здесь

В этом примере изображения «возобновить» и «выйти» могут быть любыми. (Анимация, сложная панель из множества частей, текст, спрайты, что-то невидимое, стопка — что угодно.)

Во всех случаях просто поместите Button+Touchable ниже, и у вас будет безупречная кнопка.

На самом деле: этот подход настолько прост, что вы, вероятно, будете использовать его даже для простых случаев.

Скажем, ваша кнопка — тривиальное изображение. Гораздо проще просто иметь изображение, а затем поместить на него Button+Touchable. (Вместо использования запутанной и проблематичной функции «Кнопка» в редакторе.)

Понимание ситуации...

1) Класс Unity Button.cs просто фантастический.

2) Но функция редактора "создать кнопку" - это фигня...

3) Делает кнопку "вверх ногами",

4) т. е. помещает текст/изображение под Button.cs

5) «Кнопочность» — это то, что вы должны иметь возможность добавлять к чему угодно. Именно так это работает с Button+Touchable.

6) Итак - совсем просто -

1. Имейте все, что хотите. Текст, изображение, панель, невидимка, анимация - что угодно.

2. Перетащите на него Button+Touchable — все готово.

Вот так все делают все кнопки в Unity!


Историческая заслуга: я считаю, что пользователь форума Unity signalZak первым додумался до этого много-много лет назад!

person Fattie    schedule 27.04.2016
comment
Начните с Unity 2018.2, вам больше не нужно делать какие-либо обходные пути, подобные этому: просто установите альфа-канал изображения на 0 и проверьте cullTransparentMesh в компоненте CanvasRenderer. Это приводит к невидимой кнопке без какого-либо рендеринга (вызов отрисовки). - person hanxu; 08.12.2020
comment
привет @hanxu! Весь смысл вопроса в том, чтобы сделать это правильно, то есть без использования прозрачного изображения. (решетка отбраковки не имеет отношения, вам нужно решение, которое вы можете применить ко всему, что требует сенсорного управления, и в 2018 году никаких изменений не произошло.) - person Fattie; 08.12.2020
comment
Привет, Фатти, кнопке ugui нужна графика для выполнения raycast, и установка альфы графики на 0 с установленным флажком cullTransparentMesh может сделать ее невидимой без затрат на рендеринг. Этим можно добиться просьбы разработчиков сделать невидимую кнопку. Добавьте дополнительную работу по кодированию, чтобы получить класс из текста, или переопределите UpdateGeometry, просто сделайте то же самое. И в большинстве проектов есть небольшое белое изображение n * n пикселей (например, 4 * 4) для маскировки, рисования линий и т. Д., Я бы предпочел использовать его и в этом случае, вместо того, чтобы кодировать дополнительную вещь для той же точки. - person hanxu; 09.12.2020

В качестве возможного улучшения ответа Fattie изменение базового класса Touchable на Graphic и переопределение protected void UpdateGeometry(), кажется, работает довольно хорошо, уменьшая (по общему признанию, незначительные) накладные расходы, связанные с Text.

public class Touchable:Graphic
{
    protected override void UpdateGeometry() { }
}
person taniwha    schedule 26.09.2020
comment
Это замечательная идея - надо будет проверить! Спасибо! - person Fattie; 08.12.2020

Моим первым решением было enable и disable компоненты, как показано ниже:

void showButton(Button buttonToShow, bool show)
{
    Image bImage = buttonToShow.GetComponent<Image>();
    Text bText = buttonToShow.GetComponentInChildren<Text>(); //Text is a child of the Button

    if (bImage != null)
    {
        bImage.enabled = show;
    }

    if (bText != null)
    {
        bText.enabled = show;
    }
}

но это не сработало. Если компоненты кнопки image и text оба являются disabled, событие нажатия кнопки НЕ срабатывает. Один из них ДОЛЖЕН быть enabled доступным для отправки событий кликов.

Решение состоит в том, чтобы установить альфа компонентов image и text на 0, чтобы скрыть, и на 1, чтобы показать снова. Они будут скрыты, но не отключены, и нажатие events будет работать.

public Button button;

void Start()
{
    //Show Button
    showButton(button, true);

    //Hide Button
    //showButton(button, false);
}

void showButton(Button buttonToShow, bool show)
{
    Image bImage = buttonToShow.GetComponent<Image>();
    Text bText = buttonToShow.GetComponentInChildren<Text>(); //Text is a child of the Button

    if (bImage != null)
    {
        Color tempColor = bImage.color;

        if (show)
        {
            tempColor.a = 1f; //Show 
            bImage.color = tempColor;
        }
        else
        {
            tempColor.a = 0f; //Hide 
            bImage.color = tempColor;

        }
    }

    if (bText != null)
    {
        Color tempColor = bText.color;

        if (show)
        {
            tempColor.a = 1f; //Show 
            bText.color = tempColor;
        }
        else
        {
            tempColor.a = 0f; //Hide 
            bText.color = tempColor;

        }
    }
}
person Programmer    schedule 27.04.2016

Я запустил Gimp (бесплатный графический инструмент для кодирования). Создал новое изображение (любого размера, я выбрал 10 пикселей x 10 пикселей), выбрал из расширенных (в диалоге создания), что его фон должен быть прозрачным. Сохранил файл. Экспортировал его в формате png с выбранным цветом сохранения фона. Перетащил его в Unity как спрайт. Поместите это на изображение кнопки. Отключена текстовая составляющая кнопки. Код не требуется... просто ничего не рисуйте в Gimp (это самое сложное).

person esoinila    schedule 06.09.2019