Unity框架学习--5 事件中心管理器

作用:访问其它脚本时,不直接访问,而是通过发送一条“命令”,让监听了这条“命令”的脚本自动执行对应的逻辑。

原理:
1、让脚本向事件中心添加事件,监听对应的“命令”。
2、发送“命令”,事件中心就会通知监听了这条“命令”的脚本,让它们自动执行对应的逻辑。

 

事件中心管理器:添加事件、发送命令

员工类   将方法注册进事件中心管理器

public class Cube : MonoBehaviour
{

    private void Awake()
    {
        EventCenterManager.Instance.AddListener("开工", Write);
    }

    public void Write()
    {
        transform.position += Vector3.right;
        Debug.Log("我是策划,我在写策划案");
    }
}

事件管理中心类

public class EventCenterManager : SingletonPatternBase<EventCenterManager>
{
    //键表示命令的名字
    //值表示命令具体要执行的逻辑
    Dictionary<string, UnityAction> eventsDictionary = new Dictionary<string, UnityAction>();

    public void AddListener(string key,UnityAction call)
    {
        if (eventsDictionary.ContainsKey(key))
        {
            eventsDictionary[key] += call;
        }
        else
            eventsDictionary.Add(key, call);
    }

/// <summary>
    /// 取消监听的命令
    /// </summary>
    public void RemoveListener(string key,UnityAction call)
    {
        if (eventsDictionary.ContainsKey(key))
        {
            eventsDictionary[key] -= call;
        }
    }

    //发送命令
    public void DisPatch(string key)
    {
        if (eventsDictionary.ContainsKey(key))
        {
            eventsDictionary[key]?.Invoke();
        }
    }

想要调用方法就直接DIsPatch  命令名  调用

Stopwatch类测试性能

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
using UnityEngine.Events;

/// <summary>
/// Stopwatch类的工具类,用于计算运行一段代码所用的时间
/// </summary>
public class StopwatchUtility
{
    /// <summary>
    /// 获取执行一段代码所需要的时间
    /// </summary>
    /// <param name="call"></param>
    /// <returns></returns>
    public static TimeSpan GetTime(UnityAction call)
    {
        //声明一个计数器
        Stopwatch timer = Stopwatch.StartNew();

        //开启计时器
        timer.Start();

        //要测试什么代码就将代码放在这里
        call?.Invoke();


        //停止计时器
        timer.Stop();

        //返回时间信息
        return timer.Elapsed;

    }

    public void PrintTime(UnityAction call)
    {
        UnityEngine.Debug.Log(GetTime(call));
    }
}

里氏替换原则的用法

自己写两个类来包裹两个不同的UnityAction,然后让他们继承自同一接口,就可以实现里氏替换原则

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class EventCenterManager : SingletonPatternBase<EventCenterManager>
{
    //键表示命令的名字
    //值表示命令具体要执行的逻辑
    Dictionary<string, IEventInfo> eventsDictionary = new Dictionary<string, IEventInfo>();

    public void AddListener(object command,UnityAction call)
    {
        string key = command.GetType().Name + "_" + command.ToString();
        if (eventsDictionary.ContainsKey(key))
        {
            (eventsDictionary[key] as EventInfo).action += call;
        }
        else
            eventsDictionary.Add(key,new EventInfo(call));
    }

    //传递带参数的委托
    public void AddListener<T>(object command,UnityAction<T> call)
    {
        string key = command.GetType().Name + "_" + command.ToString() + "_" + typeof(T).Name;
        if (eventsDictionary.ContainsKey(key))
        {
            (eventsDictionary[key] as EventInfo<T>).action += call;
        }
        else
            eventsDictionary.Add(key, new EventInfo<T>(call));
    }

    /// <summary>
    /// 取消监听的命令
    /// </summary>
    public void RemoveListener(object command,UnityAction call)
    {
        string key = command.GetType().Name + "_" + command.ToString();
        if (eventsDictionary.ContainsKey(key))
        {
            (eventsDictionary[key] as EventInfo).action -= call;
        }
    }

    //取消带有参数的监听事件
    public void RemoveListener<T>(object command,UnityAction<T> call)
    {
        string key = command.GetType().Name + "_" + command.ToString() + "_" + typeof(T).Name;
        if (eventsDictionary.ContainsKey(key))
        {
            (eventsDictionary[key] as EventInfo<T>).action -= call;
        }
    }

    //移除一条命令所对应的全部委托
    public void RemoveListeners(object command)
    {
        string key = command.GetType().Name + "_" + command.ToString();
        if (eventsDictionary.ContainsKey(key))
        {
            (eventsDictionary[key] as EventInfo).action = null;
        }
    }

    //带有参数的移除一条命令中所有委托
    public void RemoveListeners<T>(object command)
    {
        string key = command.GetType().Name + "_" + command.ToString() + "_" + typeof(T).Name;
        if (eventsDictionary.ContainsKey(key))
        {
            (eventsDictionary[key] as EventInfo<T>).action = null;
        }
    }

    //发送命令
    public void DisPatch(object command)
    {
        string key = command.GetType().Name + "_" + command.ToString();
        if (eventsDictionary.ContainsKey(key))
        {
            (eventsDictionary[key] as EventInfo).action?.Invoke();
        }
    }

    //给带参数的事件写的重载
    public void DisPatch<T>(object command,T parameter)
    {
        string key = command.GetType().Name + "_" + command.ToString() + "_" + typeof(T).Name;
        if (eventsDictionary.ContainsKey(key))
        {
            (eventsDictionary[key] as EventInfo<T>).action?.Invoke(parameter);
        }
    }

    /// <summary>
    /// 移除所有带或者不带参数的监听事件,切换场景可以考虑使用
    /// </summary>
    public void RemoveAllListeners()
    {
        eventsDictionary.Clear();
    }

    private interface IEventInfo { }  //仅用于里氏替换原则

    private class EventInfo:IEventInfo
    {
        public UnityAction action;

        public EventInfo(UnityAction call)
        {
            action += call;
        }
    }

    private class EventInfo<T> :IEventInfo
    {
        public UnityAction<T> action;

        public EventInfo(UnityAction<T> call)
        {
            action += call;
        }
    }

}

传递多个参数的委托事件:

  • 可以写一个信息类来存储多个信息,然后事件中传递这个信息类。这样就还是一个参数
  • 或者额外写含有两个参数的方法,写含有三个的,四个的(可行,但是费劲)
  • 元组(但是我不知道这个是什么)

猜你喜欢

转载自blog.csdn.net/zaizai1007/article/details/132295000
今日推荐