Unity Framework Learning--5 Event Center Manager

Function : When accessing other scripts, you do not access directly. Instead, you send a "command" to let the script that listens to this "command" automatically execute the corresponding logic.

Principle:
1. Let the script add events to the event center and listen for the corresponding "commands".
2. Send a "command" and the event center will notify the scripts listening to this "command" and let them automatically execute the corresponding logic.

 

Event Center Manager: Add events, send commands

Employee class registers methods into the event center manager

public class Cube : MonoBehaviour
{

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

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

Event management center class

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();
        }
    }

If you want to call a method, just call DIsPatch command name directly.

Stopwatch class test performance

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));
    }
}

How to use the Richter substitution principle

Write two classes yourself to wrap two different UnityActions, and then let them inherit from the same interface, you can implement the Liskov substitution principle

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;
        }
    }

}

Delegate events passing multiple parameters:

  • You can write an information class to store multiple pieces of information, and then pass this information class in the event. This is still a parameter
  • Or write additional methods with two parameters, three or four (feasible, but laborious)
  • Tuple (but I don’t know what this is)

Guess you like

Origin blog.csdn.net/zaizai1007/article/details/132295000