Events en C#
Cómo crear un sistema de transmisión dinámico usando Eventos
Los eventos son delegados especializados que son útiles cuando quieres alertar a otras clases que algo está ocurriendo.
En la práctica, verás que los eventos funcionan de manera similar a los delegados públicos de multidifusión. Para obtener más información sobre los delegados, por favor consulta la lección sobre delegados vinculada en la parte inferior de este tutorial.
Un evento puede considerarse como un sistema de emisión, cualquier clase que esté Interesada en un evento puede suscribirle métodos. Cuando esa situación específica ocurra, como hacer clic en un botón, un potenciador o la herida a un jugador, invocamos nuestro evento y este a su vez invoca los métodos de las clases suscritas.
Tenemos una escena con dos esferas. Una esfera tiene un script llamado
TeleportScript, mientras el otro tiene un script llamado
TurnColorScript. Anexado a nuestra cámara esta el script
EventManager
Un evento puede usarse para casi cualquier situación.
Pero en este ejemplo queremos invocar un evento cuando el jugador haga clic en un botón que estamos mostrando en la pantalla.
En nuestro
EventManager, podemos ver que primero creamos un tipo de delegado al que vamos a llamar
ClickAction().
public delegate void ClickAction();Vemos que cualquier método que desee suscribirse a nuestro evento no debe tomar parámetros y debe tener un retorno de tipo
void.
Luego, creamos nuestra variable tipo evento. Lo hacemos con la palabra reservada
event. Ten en cuenta que esta variable también es estática, de esa manera podremos usarla fuera de la clase sin tener que instanciar un objeto de esta clase.
public static event ClickAction OnClicked;Nuestra variable objeto, la misma que hemos llamado
ClickAction(), es del tipo del delegado que creamos antes. Lo único más de lo que es responsable esta clase es invocar el evento cuando la situación apropiada se presente.
Como lo hemos dicho antes, invocamos este evento cuando el jugador haga clic en nuestro botón. Por lo tanto, este script tiene un método
OnGUI(). Dentro del método
OnGUI(), creamos un botón en nuestra pantalla.
void OnGUI()
{
if(GUI.Button(new Rect(
/*x*/ Screen.width / 2 - 50,
/*y*/ 5,
/*width*/ 100,
/*height*/ 30),
/*text*/ "Click"))
{
if(OnClicked != null)
{
OnClicked();
}
}
}Cuando el jugador hace clic en el botón usamos nuestra variable evento como si fuera una función. Esto, efectivamente, invoca nuestro evento.
Ten en cuenta que, al igual que los delegados, provoca un error Si invocamos un evento sin suscriptores. Por lo tanto, siempre debemos asegurarnos de que el evento no sea igual a null antes de invocarlo.
Si recuerdas, las dos esferas en nuestra escena tienen dos scripts diferentes anexados a ellas. Estos scripts actuarán como suscriptores a ese evento. Vamos a echarle un vistazo ahora.
En el
TeleportScript hemos creado un método llamado
Teleport(). Este es el método al que suscribiremos el evento que hemos creado en el
EventManager.
Tal vez te habrás dado cuenta de que el método
Teleport() no toma parámetros y tiene un retorno tipo
void, al igual que nuestro delegado.
void Teleport()
{
Vector3 pos = transform.position;
pos.y = Random.Range(1.0f, 3.0f);
transform.position = pos;
}El método
Teleport() es el que ubica el objeto al azar a lo largo del eje vertical.
Cerca de la parte superior de nuestro script tenemos un método llamado
Teleport(). Este es un método integrado que se invocará cuando el objeto al que el script está anexado se cree o se habilite en una escena.
void OnEnable()
{
EventManager.OnClicked += Teleport;
}Usaremos este método para suscribir nuestro método
Teleport() al evento
OnClicked en el
EventScript. Podemos ver que suscribimos un evento al método usando el operador
+=.
EventManager.OnClicked += Teleport;Al suscribir un método a un evento nos aseguramos de que cuando el evento ocurra, se invocará nuestro método.
Luego, tenemos el método
OnDisable(). Al contrario del método
OnEnable() el método
OnDisable se invoca cuando se destruye o se deshabilita un objeto en una escena Dentro del método
OnDisable(), estamos cancelando la suscripción de nuestro método del evento.
void OnDisable()
{
EventManager.OnClicked -= Teleport;
}Cancelamos la suscripción de un método a un evento usando el operador
-=.
EventManager.OnClicked -= Teleport;Al hacerlo nos aseguramos de que nuestro método no se invoque más cuando ocurra un evento.
Este paso es muy importante y no hacerlo puede llevar a fugas de memoria y errores en tu juego. Una regla a seguir es que cuando suscribas un método a un evento, también debes tener la cancelación correspondiente.
Nuestro
TurnColorScript está estructurado de manera muy similar a nuestro
TurnColorScript. En este caso, tenemos un método llamado
TurnColor(), que no toma parámetros y tiene un retorno tipo void. El método
TurnColor() torna el material del objeto a un color al azar.
void TurnColor()
{
Color col = new Color(
/*r*/ Random.value,
/*g*/ Random.value,
/*b*/ Random.value);
GetComponent<Renderer>().material.color = col;
}Una vez más, tenemos los métodos
OnEnable() y
OnDisable(). Esta vez están suscribiendo y cancelando la suscripción al evento de nuestro método
TurnColor(). También vale la pena recalcar otra vez que cancelar la suscripción al evento de nuestro método es importantísimo para usar los eventos correctamente y prevenir errores en nuestro código.
void OnEnable()
{
EventManager.OnClicked += TurnColor;
}
void OnDisable()
{
EventManager.OnClicked -= TurnColor;
}De regreso en
Unity, podemos rodar nuestra escena. Lo primero de lo que te darás cuenta es el botón que aparece cerca de la parte superior.
Al hacer clic en ese botón invocamos nuestro evento e invocamos los métodos
Teleport() y
TurnColor(). Podemos hacer clic en el botón muchas veces y cada vez los métodos suscritos se invocarán. Como puedes ver, nuestro
EventManager solo debe preocuparse sobre el evento mismo y los desencadenantes del evento.
No necesitaba saber sobre los scripts
Teleport o
TurnColor. De la misma manera, esos scripts no necesitaban saber el uno sobre el otro. De esta manera, podemos crear un sistema de difusión muy robusto y flexible
Tal vez te estés preguntando por qué usamos una variable estática
event en vez de una variable delegada pública en nuestro
EventManager. Lo cierto es que puedes lograr la misma funcionalidad de
event con variables delegadas públicas.
De hecho, como lo dijimos al principio de esta lección, los eventos son delegados especializados. La razón por la que usamos
event en vez de las variables delegadas públicas para situaciones como esta es que los
event tienen seguridad integrada a ellos intrínsicamente, mientras que las variables delegadas no.
Con los
event, otras clases solo puedes suscribirse y cancelar la suscripción. Si usaras un variable delegada pública, otras clases podrían invocar o sobrescribir nuestra variable delegada para hacer cosas muy perversas.
Generalmente, si quieres crear un sistema de método dinámico que implica a más de una clase, usa las variables
event en vez de variables delegadas.
Apoya el contenido de mi blog a través de:
Fuente: