Nowy interfejs Unity - Dynamicznie zmieniaj funkcje wywoływane przez elementy GUI

17

Patrząc, aby dynamicznie zmienić wartość w przycisku OnClick i suwak On Value Zmieniono Przykład 1 przykład 2.

Gdybym musiał zgadywać, jak to zrobiono, uzyskaj odwołanie do elementu button / gui. Następnie pobierz składnik skryptu Button i uzyskaj dostęp do tej listy wywołań funkcji. Nie jestem jednak pewien, jak zmodyfikować tę listę. Czy ktoś ma jakieś pomysły?

Więcej szczegółów, które mogą pomóc:

  • Wywoływana funkcja jest niezależna od niestandardowego komponentu skryptu
  • Korzystanie z opcji zmiennej „dynamicznej” dla suwaków
  • Może służyć do tworzenia dynamicznych przycisków
thedeadlybutter
źródło

Odpowiedzi:

23

Istnieje bardzo prosty sposób na zmianę wydarzeń:

EDYTOWAĆ

Zobacz moją drugą odpowiedź, aby szybko i łatwo dodać OnClickwydarzenie tylko do wydarzenia. W przypadku innych wydarzeń, jak OnDragponiżej.


Dodatkowo, jeśli potrzebujesz czegoś więcej niż tylko domyślnie dostarczonych zdarzeń, sugeruję zamiast tego dołączyć EventTriggerdo twojego obiektu gry. To daje nam dostęp do BaseEventDataobiektu zwróconego ze zdarzenia, mówiąc nam rzeczy takie jak obiekt, który utworzył zdarzenie. Następnie możesz zrobić coś takiego:

//Create an event delegate that will be used for creating methods that respond to events
public delegate void EventDelegate(UnityEngine.EventSystems.BaseEventData baseEvent);

Następnie możemy stworzyć metodę obsługi zdarzeń, podpis musi być zgodny z podpisem naszego delegata. Musi więc zwrócić voidi zaakceptować BaseEventDatajako pierwszy i jedyny parametr:

public void DropEventMethod(UnityEngine.EventSystems.BaseEventData baseEvent) {
    Debug.Log(baseEvent.selectedObject.name + " triggered an event!");
    //baseEvent.selectedObject is the GameObject that triggered the event,
    // so we can access its components, destroy it, or do whatever.
}

Na koniec, aby dynamicznie dodać wydarzenie:

//Get the event trigger attached to the UI object
EventTrigger eventTrigger = buttonObject.GetComponent<EventTrigger>();

//Create a new entry. This entry will describe the kind of event we're looking for
// and how to respond to it
EventTrigger.Entry entry = new EventTrigger.Entry();

//This event will respond to a drop event
entry.eventID = EventTriggerType.Drop;

//Create a new trigger to hold our callback methods
entry.callback = new EventTrigger.TriggerEvent();

//Create a new UnityAction, it contains our DropEventMethod delegate to respond to events
UnityEngine.Events.UnityAction<BaseEventData> callback =
    new UnityEngine.Events.UnityAction<BaseEventData>(DropEventMethod);

//Add our callback to the listeners
entry.callback.AddListener(callback);

//Add the EventTrigger entry to the event trigger component
eventTrigger.delegates.Add(entry);

Jeśli używasz wersji 5.3.3 lub nowszej, użyj tego wiersza zamiast ostatniego wiersza powyżej, delegaci są amortyzowani :

eventTrigger.triggers.Add(entry); 
MichaelHouse
źródło
Wygląda na to, że dynamiczne dodawanie modułu obsługi nie wydaje się pojawiać w inspektorze. Szuflada nadal pokazuje „Pustą listę” dla delegatów
denerwuje
To jest poprawne. Programy obsługi dodane z kodu są oddzielone od „stałych” programów obsługi pokazanych w inspektorze; ponadto jesteś odpowiedzialny za oczyszczenie tych programów obsługi (w przeciwieństwie do tych upartych, którymi zajmuje się Unity).
Joe Strout
11

Chodzi o to, że delegate{}składnia znaleziona w mojej poprzedniej odpowiedzi jest nieaktualna, istnieje inny sposób wykonania tego za pomocą notacji lambda:

void buttonSetup(Button button) {
    //Remove the existing events
    button.onClick.RemoveAllListeners();
    //Add your new event using lambda notation
    button.onClick.AddListener (handleButton);
}

void handleButton() {
    Debug.Log("Button pressed!");
}

Lub możesz przekazać przycisk, aby uczynić rzeczy nieco bardziej dynamicznymi:

void buttonSetup(Button button) {
    button.onClick.RemoveAllListeners();
    //Add your new event
    button.onClick.AddListener(() => handleButton(button));
}

void handleButton(Button b) {
    Debug.Log("Button '" + b.name + "' pressed!");
}
MichaelHouse
źródło
Pamiętaj, że ta strategia dotyczy tylko OnClickwydarzenia. Aby dynamicznie dodawać inne zdarzenia, musisz postępować zgodnie z instrukcjami zawartymi w mojej innej odpowiedzi.
MichaelHouse
0

Utwórz nowy skrypt zgodnie z następującymi zasadami:

public class EventHandler : MonoBehaviour, IPointerClickHandler
{
    public void OnPointerClick(PointerEventData eventData)
    {
        Debug.Log("Element: " +
                   eventData.selectedObject.name +
                   " was clicked at " +
                   eventData.position.ToString());
    }
}

Ten skrypt implementuje w interfejsie IPointerClickHandler (wśród wielu innych dostępnych interfejsów ). Po prostu dołączenie tego skryptu do elementu interfejsu użytkownika pozwoli temu skryptowi przechwytywać zdarzenia kliknięcia (lub dowolne zdarzenie, dla którego implementujesz interfejs).

Następnym krokiem jest po prostu dynamiczne dodanie tego skryptu jako komponentu do żądanego elementu interfejsu użytkownika:

myButton.AddComponent<EventHandler>();

Spowoduje to dodanie skryptu jako komponentu myButtoni następnym razem, gdy kliknę przycisk, uzyskam informacje o tym, który przycisk został kliknięty i gdzie miało miejsce kliknięcie.

To zapewnia najwięcej informacji o wydarzeniu w porównaniu do moich innych odpowiedzi.

MichaelHouse
źródło
0

Sposób, w jaki jedność implementuje interfejs użytkownika, jest jak każdy inny element jedności. Dodajesz GameObject i dołączasz do niego komponenty interfejsu użytkownika. Po uzyskaniu obiektu gry możesz pobrać z niego komponenty interfejsu użytkownika i zmienić właściwości.

Odwołanie API dla interfejsu użytkownika można znaleźć w przestrzeni nazw UnityEngine.UI, odwołanie API dla BUtton to http://docs.unity3d.com/ScriptReference/UI.Button.html

Zobacz post http://blog.trsquarelab.com/2015/03/new-ui-implementation-using-c-scripts.html, aby uzyskać więcej informacji na temat uzyskiwania dostępu do interfejsu użytkownika ze skryptów C #

Ranjith
źródło