作用:访问其它脚本时,不直接访问,而是通过发送一条“命令”,让监听了这条“命令”的脚本自动执行对应的逻辑。
原理:
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;
}
}
}
传递多个参数的委托事件:
- 可以写一个信息类来存储多个信息,然后事件中传递这个信息类。这样就还是一个参数
- 或者额外写含有两个参数的方法,写含有三个的,四个的(可行,但是费劲)
- 元组(但是我不知道这个是什么)