在大型的项目中,一般需要大量的事件来实现我们的功能,如果代码之间的耦合度高,相应的扩展性就会变得差一些。要改变一些要改变的代码时就要去找相应的引用,这会非常麻烦。降低代码的耦合度,可以大大提高项目的扩展性,给我们带来了方便。
基本思路是:每一个事件码对应一种事件,通过广播事件码,来触发相应的事件。
首先我们需要建立三个脚本来分别存放和处理不同方法和逻辑
1.创建一个单例模式的基类:BaseManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 泛型基类:用于创建单例模式
/// </summary>
/// <typeparam name="T">类型</typeparam>
public class BaseManager <T> where T : new() {
private static T _Instance;
public static T GetInstance()
{
if (_Instance==null)
{
_Instance= new T();
}
return _Instance;
}
}
2.创建一个存放事件码的类(不需要继承MonoBehaviour):EventType.cs
public enum EventType
{
}
需要触发什么事件,就把事件码写在里面。
3.创建一个用来封装我们所使用到的所有委托: CallBack.cs
public delegate void CallBack();
public delegate void CallBack<X>(X arg);
public delegate void CallBack<X, Y>(X arg1,Y arg2);
public delegate void CallBack<X, Y, Z>(X arg1, Y arg2,Z arg3);
public delegate void CallBack<X, Y, Z, W>(X arg1, Y arg2, Z arg3,W arg4);
public delegate void CallBack<X, Y, Z, W, T>(X arg1, Y arg2, Z arg3, W arg,T arg5);
这里主要使用C#的泛型委托,这个代码还可以扩展更多的参数,只要你需要多少个参数就可以写多少个,一般5个参数就可以了。
4.创建一个用于处理不同事件类型的监听,移除监听,广播:EventCenter.cs
主要思路:1.通过C#的Dictionary存放事件码和事件的委托
2.添加事件:判断字典是否有该事件码,没有添加;
判断当前委托类型与添加的事件码的类型是否一致
最后订阅该事件
3.移除事件: 先判断事件码是否存在
取消订阅
最后判断事件码是否为空,是null则移除事件码。
4.广播事件:若事件委托不为null ,广播事件。
using System;
using System.Collections.Generic;
public class EventCenter : BaseManager<EventCenter>
{
public Dictionary<EventEnum, Delegate> m_EventTable = new Dictionary<EventEnum, Delegate>();
/// <summary>
/// 添加事件
/// </summary>
/// <param name="eventEnum">事件码</param>
/// <param name="callBack">事件委托</param>
public void AddListener(EventEnum eventEnum, CallBack callBack)
{
if (!m_EventTable.ContainsKey(eventEnum))
{
m_EventTable.Add(eventEnum, null);
}
Delegate d = m_EventTable[eventEnum];
if (d != null && d.GetType() != callBack.GetType())
{
throw new Exception(string.Format("尝试事件为{0}添加不同类型委托,当前委托类型为{1},要添加的委托类型为{2}", eventEnum, d.GetType(), callBack.GetType()));
}
m_EventTable[eventEnum] = (CallBack)m_EventTable[eventEnum] + callBack;
}
/// <summary>
/// one parameter
/// </summary>
/// <typeparam name="X">参数1</typeparam>
/// <param name="eventEnum">事件码</param>
/// <param name="callBack">事件委托</param>
public void AddListener<X>(EventEnum eventEnum, CallBack<X> callBack)
{
if (!m_EventTable.ContainsKey(eventEnum))
{
m_EventTable.Add(eventEnum, null);
}
Delegate d = m_EventTable[eventEnum];
if (d != null && d.GetType() != callBack.GetType())
{
throw new Exception(string.Format("尝试事件为{0}添加不同类型委托,当前委托类型为{1},要添加的委托类型为{2}", eventEnum, d.GetType(), callBack.GetType()));
}
m_EventTable[eventEnum] = (CallBack<X>)m_EventTable[eventEnum] + callBack;
}
/// <summary>
/// two parameter
/// </summary>
/// <typeparam name="X"></typeparam>
/// <typeparam name="Y"></typeparam>
/// <param name="eventEnum"></param>
/// <param name="callBack"></param>
public void AddListener<X,Y>(EventEnum eventEnum, CallBack<X,Y> callBack)
{
if (!m_EventTable.ContainsKey(eventEnum))
{
m_EventTable.Add(eventEnum, null);
}
Delegate d = m_EventTable[eventEnum];
if (d != null && d.GetType() != callBack.GetType())
{
throw new Exception(string.Format("尝试事件为{0}添加不同类型委托,当前委托类型为{1},要添加的委托类型为{2}", eventEnum, d.GetType(), callBack.GetType()));
}
m_EventTable[eventEnum] = (CallBack<X,Y>)m_EventTable[eventEnum] + callBack;
}
/// <summary>
/// three parameter
/// </summary>
/// <typeparam name="X"></typeparam>
/// <typeparam name="Y"></typeparam>
/// <typeparam name="Z"></typeparam>
/// <param name="eventEnum"></param>
/// <param name="callBack"></param>
public void AddListener<X, Y, Z>(EventEnum eventEnum, CallBack<X, Y, Z> callBack)
{
if (!m_EventTable.ContainsKey(eventEnum))
{
m_EventTable.Add(eventEnum, null);
}
Delegate d = m_EventTable[eventEnum];
if (d != null && d.GetType() != callBack.GetType())
{
throw new Exception(string.Format("尝试事件为{0}添加不同类型委托,当前委托类型为{1},要添加的委托类型为{2}", eventEnum, d.GetType(), callBack.GetType()));
}
m_EventTable[eventEnum] = (CallBack<X, Y, Z>)m_EventTable[eventEnum] + callBack;
}
/// <summary>
/// four parameter
/// </summary>
/// <typeparam name="X"></typeparam>
/// <typeparam name="Y"></typeparam>
/// <typeparam name="Z"></typeparam>
/// <typeparam name="W"></typeparam>
/// <param name="eventEnum"></param>
/// <param name="callBack"></param>
public void AddListener<X, Y, Z, W>(EventEnum eventEnum, CallBack<X, Y, Z, W> callBack)
{
if (!m_EventTable.ContainsKey(eventEnum))
{
m_EventTable.Add(eventEnum, null);
}
Delegate d = m_EventTable[eventEnum];
if (d != null && d.GetType() != callBack.GetType())
{
throw new Exception(string.Format("尝试事件为{0}添加不同类型委托,当前委托类型为{1},要添加的委托类型为{2}", eventEnum, d.GetType(), callBack.GetType()));
}
m_EventTable[eventEnum] = (CallBack<X, Y, Z, W>)m_EventTable[eventEnum] + callBack;
}
/// <summary>
/// five parameter
/// </summary>
/// <typeparam name="X"></typeparam>
/// <typeparam name="Y"></typeparam>
/// <typeparam name="Z"></typeparam>
/// <typeparam name="W"></typeparam>
/// <typeparam name="T"></typeparam>
/// <param name="eventEnum"></param>
/// <param name="callBack"></param>
public void AddListener<X, Y, Z, W, T>(EventEnum eventEnum, CallBack<X, Y, Z, W, T> callBack)
{
if (!m_EventTable.ContainsKey(eventEnum))
{
m_EventTable.Add(eventEnum, null);
}
Delegate d = m_EventTable[eventEnum];
if (d != null && d.GetType() != callBack.GetType())
{
throw new Exception(string.Format("尝试事件为{0}添加不同类型委托,当前委托类型为{1},要添加的委托类型为{2}", eventEnum, d.GetType(), callBack.GetType()));
}
m_EventTable[eventEnum] = (CallBack<X, Y, Z, W, T>)m_EventTable[eventEnum] + callBack;
}
/// <summary>
/// 移除事件
/// </summary>
/// <param name="eventEnum">事件码</param>
/// <param name="callBack">事件委托</param>
public void RemoveListener(EventEnum eventEnum, CallBack callBack)
{
if (m_EventTable.ContainsKey(eventEnum))
{
Delegate d = m_EventTable[eventEnum];
if (d == null)
{
throw new Exception(string.Format("移除事件错误:事件{0}没有对应的委托类型", eventEnum));
}
else if (d.GetType() != callBack.GetType())
{
throw new Exception(string.Format("移除事件错误:事件{0}没有对应的委托,当前委托为{1},要移除的事件为{2}", eventEnum, d.GetType(), callBack.GetType()));
}
}
else
{
throw new Exception(string.Format("移除事件错误:没有事件码{0}", eventEnum));
}
m_EventTable[eventEnum] = (CallBack)m_EventTable[eventEnum] - callBack;
if (m_EventTable[eventEnum] == null)
{
m_EventTable.Remove(eventEnum);
}
}
/// <summary>
/// one parameter
/// </summary>
/// <typeparam name="X"></typeparam>
/// <param name="eventEnum"></param>
/// <param name="callBack"></param>
public void RemoveListener<X>(EventEnum eventEnum, CallBack<X> callBack)
{
if (m_EventTable.ContainsKey(eventEnum))
{
Delegate d = m_EventTable[eventEnum];
if (d == null)
{
throw new Exception(string.Format("移除事件错误:事件{0}没有对应的委托类型", eventEnum));
}
else if (d.GetType() != callBack.GetType())
{
throw new Exception(string.Format("移除事件错误:事件{0}没有对应的委托,当前委托为{1},要移除的事件为{2}", eventEnum, d.GetType(), callBack.GetType()));
}
}
else
{
throw new Exception(string.Format("移除事件错误:没有事件码{0}", eventEnum));
}
m_EventTable[eventEnum] = (CallBack<X>)m_EventTable[eventEnum] - callBack;
if (m_EventTable[eventEnum] == null)
{
m_EventTable.Remove(eventEnum);
}
}
/// <summary>
/// two parameter
/// </summary>
/// <typeparam name="X"></typeparam>
/// <typeparam name="Y"></typeparam>
/// <param name="eventEnum"></param>
/// <param name="callBack"></param>
public void RemoveListener<X,Y>(EventEnum eventEnum, CallBack<X,Y> callBack)
{
if (m_EventTable.ContainsKey(eventEnum))
{
Delegate d = m_EventTable[eventEnum];
if (d == null)
{
throw new Exception(string.Format("移除事件错误:事件{0}没有对应的委托类型", eventEnum));
}
else if (d.GetType() != callBack.GetType())
{
throw new Exception(string.Format("移除事件错误:事件{0}没有对应的委托,当前委托为{1},要移除的事件为{2}", eventEnum, d.GetType(), callBack.GetType()));
}
}
else
{
throw new Exception(string.Format("移除事件错误:没有事件码{0}", eventEnum));
}
m_EventTable[eventEnum] = (CallBack<X,Y>)m_EventTable[eventEnum] - callBack;
if (m_EventTable[eventEnum] == null)
{
m_EventTable.Remove(eventEnum);
}
}
/// <summary>
/// three parameter
/// </summary>
/// <typeparam name="X"></typeparam>
/// <typeparam name="Y"></typeparam>
/// <typeparam name="Z"></typeparam>
/// <param name="eventEnum"></param>
/// <param name="callBack"></param>
public void RemoveListener<X, Y, Z>(EventEnum eventEnum, CallBack<X, Y, Z> callBack)
{
if (m_EventTable.ContainsKey(eventEnum))
{
Delegate d = m_EventTable[eventEnum];
if (d == null)
{
throw new Exception(string.Format("移除事件错误:事件{0}没有对应的委托类型", eventEnum));
}
else if (d.GetType() != callBack.GetType())
{
throw new Exception(string.Format("移除事件错误:事件{0}没有对应的委托,当前委托为{1},要移除的事件为{2}", eventEnum, d.GetType(), callBack.GetType()));
}
}
else
{
throw new Exception(string.Format("移除事件错误:没有事件码{0}", eventEnum));
}
m_EventTable[eventEnum] = (CallBack<X, Y, Z>)m_EventTable[eventEnum] - callBack;
if (m_EventTable[eventEnum] == null)
{
m_EventTable.Remove(eventEnum);
}
}
/// <summary>
/// four parameter
/// </summary>
/// <typeparam name="X"></typeparam>
/// <typeparam name="Y"></typeparam>
/// <typeparam name="Z"></typeparam>
/// <typeparam name="W"></typeparam>
/// <param name="eventEnum"></param>
/// <param name="callBack"></param>
public void RemoveListener<X, Y, Z, W>(EventEnum eventEnum, CallBack<X, Y, Z, W> callBack)
{
if (m_EventTable.ContainsKey(eventEnum))
{
Delegate d = m_EventTable[eventEnum];
if (d == null)
{
throw new Exception(string.Format("移除事件错误:事件{0}没有对应的委托类型", eventEnum));
}
else if (d.GetType() != callBack.GetType())
{
throw new Exception(string.Format("移除事件错误:事件{0}没有对应的委托,当前委托为{1},要移除的事件为{2}", eventEnum, d.GetType(), callBack.GetType()));
}
}
else
{
throw new Exception(string.Format("移除事件错误:没有事件码{0}", eventEnum));
}
m_EventTable[eventEnum] = (CallBack<X, Y, Z, W>)m_EventTable[eventEnum] - callBack;
if (m_EventTable[eventEnum] == null)
{
m_EventTable.Remove(eventEnum);
}
}
/// <summary>
/// five parameter
/// </summary>
/// <typeparam name="X"></typeparam>
/// <typeparam name="Y"></typeparam>
/// <typeparam name="Z"></typeparam>
/// <typeparam name="W"></typeparam>
/// <typeparam name="T"></typeparam>
/// <param name="eventEnum"></param>
/// <param name="callBack"></param>
public void RemoveListener<X, Y, Z, W, T>(EventEnum eventEnum, CallBack<X, Y, Z, W, T> callBack)
{
if (m_EventTable.ContainsKey(eventEnum))
{
Delegate d = m_EventTable[eventEnum];
if (d == null)
{
throw new Exception(string.Format("移除事件错误:事件{0}没有对应的委托类型", eventEnum));
}
else if (d.GetType() != callBack.GetType())
{
throw new Exception(string.Format("移除事件错误:事件{0}没有对应的委托,当前委托为{1},要移除的事件为{2}", eventEnum, d.GetType(), callBack.GetType()));
}
}
else
{
throw new Exception(string.Format("移除事件错误:没有事件码{0}", eventEnum));
}
m_EventTable[eventEnum] = (CallBack<X, Y, Z, W, T>)m_EventTable[eventEnum] - callBack;
if (m_EventTable[eventEnum] == null)
{
m_EventTable.Remove(eventEnum);
}
}
/// <summary>
/// 广播事件
/// </summary>
/// <param name="eventEnum"></param>
public void BraodCastEvent(EventEnum eventEnum)
{
Delegate d;
if (m_EventTable.TryGetValue(eventEnum, out d))
{
CallBack callBack = d as CallBack;
if (callBack != null)
{
callBack();
}
else
{
throw new Exception(string.Format("广播事件错误:事件{0}有不同类型的委托", eventEnum));
}
}
}
/// <summary>
/// one parameter
/// </summary>
/// <typeparam name="X"></typeparam>
/// <param name="eventEnum"></param>
/// <param name="arg"></param>
public void BraodCastEvent<X>(EventEnum eventEnum, X arg)
{
Delegate d;
if (m_EventTable.TryGetValue(eventEnum, out d))
{
CallBack<X> callBack = d as CallBack<X>;
if (callBack != null)
{
callBack(arg);
}
else
{
throw new Exception(string.Format("广播事件错误:事件{0}有不同类型的委托", eventEnum));
}
}
}
/// <summary>
/// two parameter
/// </summary>
/// <typeparam name="X"></typeparam>
/// <typeparam name="Y"></typeparam>
/// <param name="eventEnum"></param>
/// <param name="arg1"></param>
/// <param name="arg2"></param>
public void BraodCastEvent<X, Y>(EventEnum eventEnum, X arg1, Y arg2)
{
Delegate d;
if (m_EventTable.TryGetValue(eventEnum, out d))
{
CallBack<X,Y> callBack = d as CallBack<X,Y>;
if (callBack != null)
{
callBack(arg1,arg2);
}
else
{
throw new Exception(string.Format("广播事件错误:事件{0}有不同类型的委托", eventEnum));
}
}
}
/// <summary>
/// three parameter
/// </summary>
/// <typeparam name="X"></typeparam>
/// <typeparam name="Y"></typeparam>
/// <typeparam name="Z"></typeparam>
/// <param name="eventEnum"></param>
/// <param name="arg1"></param>
/// <param name="arg2"></param>
/// <param name="arg3"></param>
public void BraodCastEvent<X, Y, Z>(EventEnum eventEnum, X arg1, Y arg2, Z arg3)
{
Delegate d;
if (m_EventTable.TryGetValue(eventEnum, out d))
{
CallBack<X, Y, Z> callBack = d as CallBack<X, Y, Z>;
if (callBack != null)
{
callBack(arg1, arg2, arg3);
}
else
{
throw new Exception(string.Format("广播事件错误:事件{0}有不同类型的委托", eventEnum));
}
}
}
/// <summary>
/// four parameter
/// </summary>
/// <typeparam name="X"></typeparam>
/// <typeparam name="Y"></typeparam>
/// <typeparam name="Z"></typeparam>
/// <typeparam name="W"></typeparam>
/// <param name="eventEnum"></param>
/// <param name="arg1"></param>
/// <param name="arg2"></param>
/// <param name="arg3"></param>
/// <param name="arg4"></param>
public void BraodCastEvent<X, Y, Z, W>(EventEnum eventEnum, X arg1, Y arg2, Z arg3, W arg4)
{
Delegate d;
if (m_EventTable.TryGetValue(eventEnum, out d))
{
CallBack<X, Y, Z, W> callBack = d as CallBack<X, Y, Z, W>;
if (callBack != null)
{
callBack(arg1, arg2, arg3, arg4);
}
else
{
throw new Exception(string.Format("广播事件错误:事件{0}有不同类型的委托", eventEnum));
}
}
}
/// <summary>
/// five parameter
/// </summary>
/// <typeparam name="X"></typeparam>
/// <typeparam name="Y"></typeparam>
/// <typeparam name="Z"></typeparam>
/// <typeparam name="W"></typeparam>
/// <typeparam name="T"></typeparam>
/// <param name="eventEnum"></param>
/// <param name="arg1"></param>
/// <param name="arg2"></param>
/// <param name="arg3"></param>
/// <param name="arg4"></param>
/// <param name="arg5"></param>
public void BraodCastEvent<X, Y, Z, W, T>(EventEnum eventEnum, X arg1, Y arg2, Z arg3, W arg4, T arg5)
{
Delegate d;
if (m_EventTable.TryGetValue(eventEnum, out d))
{
CallBack<X, Y, Z, W, T> callBack = d as CallBack<X, Y, Z, W, T>;
if (callBack != null)
{
callBack(arg1, arg2, arg3, arg4, arg5);
}
else
{
throw new Exception(string.Format("广播事件错误:事件{0}有不同类型的委托", eventEnum));
}
}
}
}
我们来做个试验,使用没有参数的。给一个场景创建一个Cube,点击按钮时显示出来
首先在EventType脚本中添加一个事件码:
public enum EventType
{
Test,
}
给Cube添加一个脚本Test
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour {
void Start () {
this.gameObject.SetActive(false);
EventCenter.GetInstance().AddListener(EventType.Test, Show);
}
void Show()
{
this.gameObject.SetActive(true);
}
private void OnDestroy()
{
EventCenter.GetInstance().RemoveListener(EventType.Test, Show);
}
}
创建一个Canvas,在Canvas下创建一个Button,给Button组件添加一个脚本Play.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Player : MonoBehaviour {
private Button button;
private void Start()
{
button = GetComponent<Button>();
button.onClick.AddListener(()=> { EventCenter.GetInstance().BraodCastEvent(EventType.Test); });
}
}
点击按钮就可以看到效果了!!
接下来在进行一个测试:有参数的;在刚刚的Canvas下创建一个Text组件
修改一下上面的Test脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Test01 : MonoBehaviour {
private Text text;
void Start () {
text = GameObject.Find("Text").GetComponent<Text>();
this.gameObject.SetActive(false);
EventCenter.GetInstance().AddListener<string,string>(EventType.Test, Show);
}
void Show(string str1,string str2)
{
this.gameObject.SetActive(true);
text.text = str1 + str2;
}
private void OnDestroy()
{
EventCenter.GetInstance().RemoveListener<string ,string>(EventType.Test, Show);
}
}
再次修改Play.cs脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Player : MonoBehaviour {
private Button button;
private void Start()
{
button = GetComponent<Button>();
button.onClick.AddListener(()=> { EventCenter.GetInstance().BraodCastEvent<string,string>(EventType.Test,"你好:","Unity!!!!"); });
}
}
点击按钮就可以看到效果了!!!
到此事件监听与广播系统就完成了!!!!