Unity事件系统(委托与回调函数)

1.理解事件系统

事件系统可以理解为,有一个呼叫者【唯一性】发出一种特定的信号(激活事件的函数),一个或多个监听者监听它所监听信号(事件注册/撤销),如果匹配则监听者会实施相应动作(回调函数)。

2.事件系统的整体框架

3.简易版事件系统

        1.事件中心

        event声明这是一个事件,提供注册订阅与撤销订阅的机制,组织外部直接触发事件。

        委托在c#中有四种:

                1.Action:无返回值的泛型委托

                2.delegate:可有可无返回值

                3.Func:有返回值的泛型委托

                4.Predicate:只有一个参数,返回值为bool

public static class EventHandler
{
    public static event Action<int> Event; //定义事件
    public static void CallEvent(int a) 
    {
        Event?.Invoke(a); //激活事件注册的回调函数
    }
}

        2.事件监听

                1.事件的注册/撤销放在OnEnable与OnDisable中,在启用和关闭脚本时进行注册/撤销

                2.回调函数:将自己当作参数传入其他函数中,而在事件系统中接收回调函数的函数是委托,委托相当于容器,里面存放着注册的回调函数。

                注:取消订阅是为了垃圾回收与防止空引用

public class EventListener : MonoBehaviour
{
    //注册事件
    private void OnEnable() 
    {
        EventHandler.Event += CallbackFunction;
    }

    //注销事件
    private void OnDisable() 
    {
        EventHandler.Event -= CallbackFunction;
    }

    //回调函数
    private void CallbackFunction(int a) 
    {
        Debug.Log(this + ":" + a);
    }
}

        3.事件呼叫

public class Caller : MonoBehaviour
{
    private void Awake() 
    {
        //呼叫事件
        EventHandler.CallEvent(30);
    }
}

4.进阶版事件系统 

        1.事件中心

                1.基类

                UnityAction是Unity定义的委托类型

public class BaseEventSO<T> : ScriptableObject
{
    [TextArea] public string description;
    
    public UnityAction<T> OnEventRaised;
    
    public void RaisEvent(T value)
    {
        OnEventRaised?.Invoke(value);//呼叫一般具有唯一性
    }
}

                2.实现类 

                注:创建对应的SO文件,一般传入参数不同需要创建不同实现类与该实现类的SO文件

[CreateAssetMenu(fileName = "ObjectEventSO", menuName = "Events/ObjectEventSO")]

public class ObjectEventSO : BaseEventSO<int>
{
    
}

        2. 事件监听

                1.基类

                UnityEvent类似于一个回调函数的集合并且可以在编辑器中可视化(对委托的封装)。

public class BaseEventListener<T> : MonoBehaviour
{
    [Header("事件监听")]
    public BaseEventSO<T> eventSO;

    [Header("事件系统(回调函数)")]
    public UnityEvent<T> reponse;

    private void OnEnable()
    {
        if (eventSO != null)
            eventSO.OnEventRaised += OnEventRasised;
    }

    private void OnDisable()
    {
        if (eventSO != null)
            eventSO.OnEventRaised -= OnEventRasised;
    }

    private void OnEventRasised(T value)
    {
        reponse.Invoke(value);
    }
}

                2.实现类

public class ObjectEventListener : BaseEventListener<int>
{
    
}

        3.事件呼叫

public class Caller : MonoBehaviour
{
    [Header("事件广播")] 
    public ObjectEventSO afterEvent;

    private void Awake() 
    {
        afterEvent.RaisEvent(30);
    }
}