Unity简易的事件系统
主要的三个脚本:
EventCenter, EventType, CallBack
EventCenter:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class EventCenter
{
private static Dictionary<EventType, Delegate> m_eventTable = new Dictionary<EventType, Delegate>();
private static void OnAddListening(EventType eventType, Delegate callBack)
{
//安全校验
if (! m_eventTable.ContainsKey(eventType))
{
m_eventTable.Add(eventType, null);
}
Delegate d = m_eventTable[eventType];
if (d != null && d.GetType() != callBack.GetType())
{
//参数不对
throw new Exception(string.Format("添加监听错误: 参数不对 应添加的参数类型:{0} 传入的参数类型{1}", d.GetType(), callBack.GetType()));
}
}
private static void OnRemoving(EventType eventType, Delegate callBack)
{
//安全校验
if (!m_eventTable.ContainsKey(eventType))
{
throw new Exception(string.Format("移除监听错误:没有对应事件类型Key : {0}", eventType));
}
Delegate d = m_eventTable[eventType];
if (d == null)
{
throw new Exception(string.Format("移除监听错误: 监听列表这个Key的回调为空 Key :{0} ", eventType));
}else if ( d.GetType() != callBack.GetType())
{
//参数不对
throw new Exception(string.Format("移除监听错误: 参数不对 应添加的参数类型:{0} 传入的参数类型{1}", d.GetType(), callBack.GetType()));
}
}
private static void OnRemoved(EventType eventType, Delegate callBack)
{
//移除监听最后 移除Key
if (m_eventTable[eventType] != null)
{
m_eventTable.Remove(eventType);
}
}
//------------------------- no parameters------------------
public static void AddListener(EventType eventType, CallBack callBack)
{
OnAddListening(eventType, callBack);
m_eventTable[eventType] = (CallBack)m_eventTable[eventType] + callBack;
}
public static void ReMoveListener(EventType eventType, CallBack callBack)
{
OnRemoving(eventType, callBack);
m_eventTable[eventType] = (CallBack)m_eventTable[eventType] - callBack;
OnRemoved(eventType, callBack);
}
public static void Broadcast(EventType eventType)
{
Delegate d;
if (m_eventTable.TryGetValue(eventType, out d))
{
CallBack callBack = d as CallBack;
if (callBack != null)
{
callBack();
}
else
{
throw new Exception(string.Format("广播失败: callBack 找不到 类型错误 Key : {0} ", eventType));
}
}
else
{
throw new Exception(string.Format("广播失败: 没有获取到广播列表 key的CallBack Key : {0} ", eventType));
}
}
//--------------------- one parameters--------------------------
public static void AddListener<T>(EventType eventType, CallBack<T> callBack)
{
OnAddListening(eventType, callBack);
m_eventTable[eventType] = (CallBack<T>)m_eventTable[eventType] + callBack;
}
public static void ReMoveListener<T>(EventType eventType, CallBack<T> callBack)
{
OnRemoving(eventType, callBack);
m_eventTable[eventType] = (CallBack<T>)m_eventTable[eventType] - callBack;
OnRemoved(eventType, callBack);
}
public static void Broadcast<T>(EventType eventType, T arg1)
{
Delegate d;
if (m_eventTable.TryGetValue(eventType, out d))
{
CallBack<T> callBack = d as CallBack<T>;
callBack(arg1);
}
else
{
throw new Exception(string.Format("广播失败: 没有获取到广播列表 key的CallBack 请检查相应参数是否对应 Key : {0} ", eventType));
}
}
//--------------- two parameters-------------------------------
public static void AddListener<T,X>(EventType eventType, CallBack<T,X> callBack)
{
OnAddListening(eventType, callBack);
m_eventTable[eventType] = (CallBack<T,X>)m_eventTable[eventType] + callBack;
}
public static void ReMoveListener<T,X>(EventType eventType, CallBack<T,X> callBack)
{
OnRemoving(eventType, callBack);
m_eventTable[eventType] = (CallBack<T,X>)m_eventTable[eventType] - callBack;
OnRemoved(eventType, callBack);
}
public static void Broadcast<T,X>(EventType eventType, T arg1, X arg2)
{
Delegate d;
if (m_eventTable.TryGetValue(eventType, out d))
{
CallBack<T,X> callBack = d as CallBack<T,X>;
callBack(arg1, arg2);
}
else
{
throw new Exception(string.Format("广播失败: 没有获取到广播列表 key的CallBack 请检查相应参数是否对应 Key : {0} ", eventType));
}
}
//----------------- three parameters--------------------------------
public static void AddListener<T,X,Y>(EventType eventType, CallBack<T,X,Y> callBack)
{
OnAddListening(eventType, callBack);
m_eventTable[eventType] = (CallBack<T,X,Y>)m_eventTable[eventType] + callBack;
}
public static void ReMoveListener<T, X, Y>(EventType eventType, CallBack<T, X, Y> callBack)
{
OnRemoving(eventType, callBack);
m_eventTable[eventType] = (CallBack<T, X, Y>)m_eventTable[eventType] - callBack;
OnRemoved(eventType, callBack);
}
public static void Broadcast<T, X, Y>(EventType eventType, T arg1, X arg2, Y arg3)
{
Delegate d;
if (m_eventTable.TryGetValue(eventType, out d))
{
CallBack<T, X, Y> callBack = d as CallBack<T, X, Y>;
callBack(arg1, arg2, arg3);
}
else
{
throw new Exception(string.Format("广播失败: 没有获取到广播列表 key的CallBack 请检查相应参数是否对应 Key : {0} ", eventType));
}
}
//--------------- four parameters---------------------------------------
public static void AddListener<T, X, Y, Z>(EventType eventType, CallBack<T, X, Y,Z> callBack)
{
OnAddListening(eventType, callBack);
m_eventTable[eventType] = (CallBack<T, X, Y,Z>)m_eventTable[eventType] + callBack;
}
public static void ReMoveListener<T,X,Y,Z>(EventType eventType, CallBack<T,X,Y,Z> callBack)
{
OnRemoving(eventType, callBack);
m_eventTable[eventType] = (CallBack<T,X,Y,Z>)m_eventTable[eventType] - callBack;
OnRemoved(eventType, callBack);
}
public static void Broadcast<T, X, Y, Z>(EventType eventType, T arg1, X arg2, Y arg3, Z arg4)
{
Delegate d;
if (m_eventTable.TryGetValue(eventType, out d))
{
CallBack<T, X, Y, Z> callBack = d as CallBack<T, X, Y, Z>;
callBack(arg1, arg2, arg3, arg4);
}
else
{
throw new Exception(string.Format("广播失败: 没有获取到广播列表 key的CallBack 请检查相应参数是否对应 Key : {0} ", eventType));
}
}
//------------------- five parameters-------------------------------------
public static void AddListener<T,X,Y,Z,W>(EventType eventType, CallBack<T,X,Y,Z,W> callBack)
{
OnAddListening(eventType, callBack);
m_eventTable[eventType] = (CallBack<T,X,Y,Z,W>)m_eventTable[eventType] + callBack;
}
public static void ReMoveListener<T, X, Y, Z, W>(EventType eventType, CallBack<T, X, Y, Z, W> callBack)
{
OnRemoving(eventType, callBack);
m_eventTable[eventType] = (CallBack<T, X, Y, Z, W>)m_eventTable[eventType] - callBack;
OnRemoved(eventType, callBack);
}
public static void Broadcast<T, X, Y, Z, W>(EventType eventType, T arg1, X arg2, Y arg3, Z arg4, W arg5)
{
Delegate d;
if (m_eventTable.TryGetValue(eventType, out d))
{
CallBack<T, X, Y, Z, W> callBack = d as CallBack<T, X, Y, Z, W>;
callBack(arg1, arg2, arg3, arg4, arg5);
}
else
{
throw new Exception(string.Format("广播失败: 没有获取到广播列表 key的CallBack 请检查相应参数是否对应 Key : {0} ", eventType));
}
}
}
EventType:
public enum EventType
{
ShowTextNone,
ShowTextOne,
//根据需要添加
}
CallBack:
public delegate void CallBack();
public delegate void CallBack<T>(T arg1);
public delegate void CallBack<T, X>(T arg1, X arg2);
public delegate void CallBack<T, X, Y>(T arg1, X arg2, Y arg3);
public delegate void CallBack<T, X, Y, Z>(T arg1, X arg2, Y arg3, Z arg4);
public delegate void CallBack<T, X, Y, Z, W>(T arg1, X arg2, Y arg3, Z arg4, W arg5);
使用:
用一个Text 和 按钮来演示
测试脚本 ShowText : 挂在Text文本组件上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ShowText : MonoBehaviour {
private Text myText;
void Awake()
{
EventCenter.AddListener(EventType.ShowTextNone, ShowName);
EventCenter.AddListener<string>(EventType.ShowTextOne, ShowNameByStr);
myText = GetComponent<Text>();
}
void OnDestroy()
{
EventCenter.ReMoveListener(EventType.ShowTextNone, ShowName);
EventCenter.ReMoveListener<string>(EventType.ShowTextOne, ShowNameByStr);
}
private void ShowName()
{
myText.text = "TanStudio";
}
private void ShowNameByStr(string str)
{
if (str == null || str == "")
{
str = "默认显示这个哦";
}
myText.text = str;
}
}
按钮测试脚本: TestBtnClick 挂在按钮组件上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TestBtnClick : MonoBehaviour {
Button myBtn;
void Awake()
{
myBtn = GetComponent<Button>();
myBtn.onClick.AddListener(
()=> EventCenter.Broadcast<string>(EventType.ShowTextOne, "哈哈哈")
);
}
}
效果图:
运行之前: 搭建的测试场景
运行之后 点击 按钮触发脚本
收到了广播事件
结尾
这个算是一个自学的 记录 博客
有一些不足的地方 比如 传参对应 太麻烦, 不像lua语言 不定参数 老是要写重载方法。。
好处就是 解耦 不用在别的脚本里调用另一个脚本 通过广播事件的方式来控制
讲一下大概实现的思路, 你们没有必要完全按上面的代码来。可以自由发挥
一个EventCenter类 把事件和回调函数 存起来管理。 用字典 比较方便
一个EventType类 作为事件的Key 可以是枚举也可以是字符串 比较喜欢枚举 这样不会重复
一个CallBack类 作为泛型回调 这样可以满足大多数函数 可以传入多个参数 上面只写了5个 可以加更多