Unity – przypisanie EventHandlerów z tablicy zewnętrznych obiektów

(oczywiście przy użyciu C#)

Ostatnio zdarzyło mi się powrócić do Unity (przynajmniej na chwilę) i udało mi się natrafić na pewien problem, którego rozwiązanie – przynajmniej na pierwszy rzut oka – nie jest zbyt oczywiste.

 

Intro


A więc załóżmy, że mamy skrypt, w którym posiadamy 2 niepowiązane ze sobą tablice:

  1. tablica przycisków (buttons)
  2. tablica obiektów jakiejś zewnętrznej klasy, której metodę chcemy wywołać na zdarzenie OnClick (listeners)

To co mamy w chwili startowej to niepowiązane ze sobą obiekty przycisków (buttons) oraz kontrolerów (controllers), same kontrolery mogą być podczepione do innego zewnętrznego obiektu z racji większej wygody i chęci odseparowania pewnej logiki od samego przycisku (i tak jest w tym przypadku).

W naszym przypadku rozmiar obu tablic jest identyczny oraz same obiekty są w relacji 1-1, tzn 1-szy button po zdarzeniu OnClick powinien wywołać metodę Toggle() 1-szego kontrolera, itd.

 

Rozwiązanie


Pierwsze podejście

Rozwiązanie wydaje się oczywiste:

Jednakże to rozwiązanie , które na pozór powinno przypisać i-temu przyciskowi – i-ty Toggle tego nie robi. W momencie wygenerowania zdarzenia OnClick (używając dowolnego przycisku) otrzymujemy informację o błędzie (crash):

IndexOutOfRangeException: Array index is out of range.

Ze wskazaniem na linię dodającą listener do przycisku (w powyższym listingu to linia 8).

 

Drugie podejście

Na pierwszy rzut oka nie widać nigdzie wyjścia poza zakres tablicy (a to się dzieje gdy spróbujemy kliknąć dowolny przycisk), jak się okazuje wyrażenia lambda używają wszędzie najnowszej wartości i, która przy takim zapisie jest zawsze identyczna i wynosi rozmiar tablicy (n), czyli mamy oczywiste wyjście poza zakres tablicy.

Przykład: jeżeli zastosowalibyśmy tablice o rozmiarze 5 (controllers[5]), to za każdym razem próbowalibyśmy przypisać Toggle z obiektu controllers[5], a jak wiadomo element o takim indeksie nie istnieje.

Rozwiązanie okazuje się trywialne i wymagające utworzenia zmiennej wewnątrz pętli będącą kopią licznika pętli oraz wrappera na funkcję, co także nieco ułatwi (zwiększy czytelność) bardziej złożone wyrażenia.

Taka konstrukcja zapewnia poprawne podłączenie event handlerów do przycisków.

Code ON!