Unity desvincula el proyecto a través de eventos globales

Si una clase quiere llamar a un método de otra clase, por ejemplo, A quiere llamar a un método de B.
Forma 1: Referencia
La forma más sencilla es que A tenga una referencia a la clase B, es decir, A posea un objeto miembro de B.
Método 2: modo de diseño (modo intermediario)
o A y B pertenecen al mismo objeto C, se llaman entre sí a través del objeto C (modo intermediario), como el grupo QQ, A y B no tienen amigos entre sí, pero ambos están en el mismo grupo QQ C, pueden hablar entre ellos en C.
Método 3: Estático (normalmente modo singleton, B es una clase de gestión, etc.)
Configure el método en B como un método estático.
Sin embargo, en el proyecto hay más de N categorías, A y B son completamente irrelevantes, y no es apropiado tener referencias entre sí, y no son clases de herramientas, por lo que no deben establecerse como métodos estáticos. Entonces, en este momento, ¿cómo hacemos que A y B establezcan una conexión?
La respuesta es usar el sistema de eventos global.
Extraiga una lista de eventos a los que se puede acceder globalmente (diccionario)

public class EventManager : MonoBehaviour
{
    
    

    public static Dictionary<EventType, List<Delegate>> EventDic = new Dictionary<EventType, List<Delegate>>();

    public delegate void CallBack();
    public delegate void CallBack<T>(T parameter);

    public static void AddListener(EventType eventType, CallBack callBack)
    {
    
    
        if (EventDic.ContainsKey(eventType))
        {
    
    
            EventDic[eventType].Add(callBack);
        }
        else
        {
    
    
            EventDic.Add(eventType, new List<Delegate>() {
    
     callBack });
        }
    }

    public static void RemoveListener(EventType eventType, CallBack callBack)
    {
    
    
        if (EventDic.ContainsKey(eventType))
        {
    
    
            CallBack currentCallBack = null;
            foreach (var item in EventDic[eventType])
            {
    
    
                currentCallBack = item as CallBack;
                if (currentCallBack == callBack)
                {
    
    
                    currentCallBack = callBack;
                }
            }
            if (currentCallBack != null)
            {
    
    
                EventDic[eventType].Remove(callBack);
            }
            if (EventDic[eventType].Count == 0)
            {
    
    
                EventDic.Remove(eventType);
            }
        }
        else
        {
    
    
            throw new Exception("当前系统未注册该事件");
        }
    }

    public static void AddListener<T>(EventType eventType, CallBack<T> callBack)
    {
    
    
        if (EventDic.ContainsKey(eventType))
        {
    
    
            EventDic[eventType].Add(callBack);
        }
        else
        {
    
    
            EventDic.Add(eventType, new List<Delegate>() {
    
     callBack });
        }
    }

    public static void RemoveListener<T>(EventType eventType, CallBack<T> callBack)
    {
    
    
        if (EventDic.ContainsKey(eventType))
        {
    
    
            CallBack<T> currentCallBack = null;
            foreach (var item in EventDic[eventType])
            {
    
    
                currentCallBack = item as CallBack<T>;
                if (currentCallBack == callBack)
                {
    
    
                    currentCallBack = callBack;
                }
            }
            if (currentCallBack != null)
            {
    
    
                EventDic[eventType].Remove(callBack);
            }
            if (EventDic[eventType].Count == 0)
            {
    
    
                EventDic.Remove(eventType);
            }
        }
        else
        {
    
    
            throw new Exception("当前系统未注册该事件");
        }
    }



    public static void Dispatch(EventType eventType)
    {
    
    
        if (EventDic.ContainsKey(eventType))
        {
    
    
            CallBack callBack;
            foreach (var item in EventDic[eventType])
            {
    
    
                callBack = item as CallBack;
                if (callBack != null)
                {
    
    
                    callBack();
                }
            }
        }
        else
        {
    
    
            throw new Exception("当前事件系统不包含该事件");
        }
    }

    public static void Dispatch<T>(EventType eventType, T parameter)
    {
    
    
        if (EventDic.ContainsKey(eventType))
        {
    
    
            CallBack<T> callBack;
            foreach (var item in EventDic[eventType])
            {
    
    
                callBack = item as CallBack<T>;
                if (callBack != null)
                {
    
    
                    callBack(parameter);
                }
            }
        }
        else
        {
    
    
            throw new Exception("当前事件系统不包含该事件");
        }
    }

}

public class EventData 
{
    
    
    public int money;
}

public enum EventType
{
    
    
    AddMoney,
    AddMoneyWithParameter,
    AddMoneyWithEventData,
}

El índice es una enumeración y el valor es un tipo de delegado.
Luego, A y B registran los métodos que necesitan llamar externamente.
Aquí hay un ejemplo de un jefe empleado.
El jefe proporciona un método para recolectar dinero y el empleado es responsable de llamarlo.

public class Boss: MonoBehaviour
{
    
    
    public Button AddListenerButton;
    public Button RemoveListenerButton;

    void Awake()
    {
    
    
        AddListenerButton.onClick.AddListener(() =>
        {
    
    
            EventManager.AddListener(EventType.AddMoney, GetMoney);
            EventManager.AddListener<int>(EventType.AddMoneyWithParameter, GetMoneyWihtPrameter);
            EventManager.AddListener<EventData>(EventType.AddMoneyWithEventData, GetmoneyWithEventData);
        });

        RemoveListenerButton.onClick.AddListener(() =>
        {
    
    
            EventManager.RemoveListener(EventType.AddMoney, GetMoney);
            EventManager.RemoveListener<int>(EventType.AddMoneyWithParameter, GetMoneyWihtPrameter);
            EventManager.RemoveListener<EventData>(EventType.AddMoneyWithEventData, GetmoneyWithEventData);
        });
    }
    void GetMoney()
    {
    
    
        Debug.Log("收到用户购买的资金,员工真棒");
    }
    void GetMoneyWihtPrameter(int money)
    {
    
    
        Debug.Log("收到用户购买的资金,员工真棒,收入赚了  " + money);
    }

    void GetmoneyWithEventData(EventData data) 
    {
    
    
        Debug.Log("通过事件数据收到用户购买的资金,员工真棒,收入赚了  " + data.money);
    }
}

public class Staff : MonoBehaviour
{
    
    
    public Button BuyButton;

    public Button BuyButtonWithParameter;

    public Button BuyButtonWithEventData;

    private void Start()
    {
    
    
        BuyButton.onClick.AddListener(() =>
        {
    
    
            EventManager.Dispatch(EventType.AddMoney);
        });
        BuyButtonWithParameter.onClick.AddListener(() =>
        {
    
    
            EventManager.Dispatch(EventType.AddMoneyWithParameter, 100);
        });
        BuyButtonWithEventData.onClick.AddListener(() =>
        {
    
    
            EventManager.Dispatch(EventType.AddMoneyWithEventData, new EventData() {
    
     money = 200});
        });
    }
}

El efecto real se demuestra de la siguiente manera:
inserte la descripción de la imagen aquí
Resumen:
los genéricos se usan en eventos globales (el tipo de datos se determina al llamar), la clase principal puede aceptar todas las subclases (el delegado puede recibir todas las subclases), la sobrecarga (los métodos registrados pueden tener parámetros y No puede tener parámetros) tres partes.
Algo similar al modo intermediario, el evento global actúa como un intermediario para proporcionar un registro de eventos y una llamada al mundo exterior, solucionando el problema del desacoplamiento entre clases.
manifestación

Supongo que te gusta

Origin blog.csdn.net/qq_40629631/article/details/121545729
Recomendado
Clasificación