Voy a profundizar un poco lo que es la cuestión. Este tema viene por los MOBAS u otros juegos en los que los que haya buffs y debuffs en tiempo real.
Voy a usar la nomenclatura del LoL que fue tal como me lo explicaron a mí.
Tenemos a Player A con su AD = 10
Se compra la espada de Doran que aumenta en +8 su AD.
Una forma simple sería que al comprar la espada, su script buscase el stats del personaje y se lo añadiese. Pero ahora viene el inconveniente ¿y objetos que tienen habilidades especiales o que su extra es un %? ¿O efectos que son temporales como un extra de daño o un slow? Tendríamos que crear scripts personalizados para este tipo de eventos con lo que no estaríamos reutilizando nuestro código y a la hora de realizar un cambio, podría afectar a otras partes del código.
En este caso, usamos Delegates. Digamos sin entrar en detalles que un delegate es una función a la que los scripts pueden inscribirse y no importa quien ejecute la llamada que todos los que estén inscritos actuarán en consonancia con esa función dependiendo de lo que realice el script subscrito.
Voy a usar c# que es el que uso para Unity3D
# DELEGATE
public class PlayerEvents : Monobehaviour{
// Declaración del Delegate
public delegate void PlayerBuff(TypeStat statAffected, float valueAffected);
// Declaración de los eventos a los que los scripts se subscriben
public static event PlayerBuff onPlayerStatUp;
public static event PlayerBuff onPlayerStatDown;
public static void PlayerStatUp(TypeStat statAffected, float valueAffected){
if(onPlayerStatUp != null)
onPlayerStatUp(statAffected, valueAffected);
}
public static void PlayerStatDown(TypeStat statAffected, float valueAffected){
if(onPlayerStatDown != null)
onPlayerStatDown(statAffected, valueAffected);
}
}
#PLAYER CONTROLLER
public class PlayerController : Monobehaviour {
Stats statsPlayer[TypeStats.Count];
//Al activarse el jugador
public void Awake(){
//Nos subscribimos al evento de Buffs
PlayerEvents.onPlayerStatUp += this.PlayerStatUp;
PlayerEvents.onPlayerStatDown += this.PlayerStatDown;
}
//Al destruirse
public void Destroy(){
//Nos desubscribimos al evento de Buffs
PlayerEvents.onPlayerStatUp -= this.PlayerStatUp;
PlayerEvents.onPlayerStatDown -= this.PlayerStatDown;
}
//Podremos tener funciones que recojan las otras 2 si queremos que se puedan activar y desactivar a nuestro antojo y añadirlas en Awake y en Destroy/Disable.
public void PlayerStatUp(TypeStat statAffected, float valueAffected){
statsPlayer[statAffected] += valueAffected;
}
public void PlayerStatDown(TypeStat statAffected, float valueAffected){
statsPlayer[statAffected] -= valueAffected;
}
}
#Script Item
public class Item : Monobehaviour{
public void Awake{
PlayerEvent.PlayerStatUP(TypeStat.AD, 8f);
}
public void Destroy{
PlayerEvent.PlayerStatDown(TypeStat.AD, 8f);
}
}
No tengo ahora manera de comprobar si es funcional y hasta después de unas horas no volveré a casa. A ver si hago algo con Unity3D para que podáis verlo.
Con estos ejemplos, hacemos que el personaje esté subscrito a esos eventos y que al añadir el script del item, este lance la función y se vea afectado el jugador, sin tener que mantener referencias de variables entre scripts dentro de un mismo objeto, además sin importar cuantos se añaden o que realicen.
La ventaja de usar Delegates es que tiene mil y un uso. La contrapartida es que son eventos que están en constante ejecución y hay que tener muy controlado el deshabilitarse cuando no van a ser usados.
Una utilidad para los delegates es activar y desactivar el movimiento del personaje desde una función. Alterar el como se mueve al estar confuso. El lanzar el evento y todos los objetos que estén subscritos se vean afectados por igual.
Imaginad el comecocos. Todos los fantasmas están subscritos al evento de que Pacman coge la cereza pero como este no está activo, actúan normalmente recorriendo el mapa. Entonces Pacman se come la cereza activando el evento del Delegate que hace que los fantasmas se tornen blancos, cambien su IA por una huidiza y que encima puedan ser comidos por Pacman. Además se activa un contador indicando con la música el tiempo restante. Una vez pasado el tiempo estipulado, se desactiva ese evento del Delegate y como se desactiva, vuelven los fantasmas a utilizar su IA normal y el destruir a Pacman. De esta manera, es el Actor el que tiene el peso del control de lo que ocurre, en vez de ser un Controlador el que maneje todo o teniendo que hacer referencia a elementos dentro de la pantalla y actuar sobre ellos.