事件系统基础理论大家可以去自行搜索理解,这里暂且不谈(后续可能会讲),本章讲的是如何使用,个人观点:即使你不太理解事件系统,但如果你用的多了,后面理解时也会更轻松,会有一种原来这就是事件系统,我之前用到过的感慨。话不用多说,直接上干货:
1 定义事件:
/// <summary>
/// 事件字典
/// </summary>
private Dictionary<string, Action<object>> eventDictionary = new Dictionary<string, Action<object>>();
//事件的队列
private Queue<QueuedEvent> eventQueue = new Queue<QueuedEvent>();
public class QueuedEvent
{
public string EventName { get; set; }
public object Arg { get; set; }
}
eventDictionary 前面的string是你事件的名字,后面的是所需要执行的方法名。起到的作用大概相当于快递站,你得告诉工作人员你的名字或者你的取件码才能找到对应的快递。
至于队列部分,暂且不谈,在监听事件里会用到
2 监听事件:
/// <summary>
/// 监听事件
/// </summary>
/// <param name="eventName"></param>
/// <param name="listener"></param>
public void StartListening(string eventName, Action<object> listener)
{
if (eventDictionary.ContainsKey(eventName))
{
eventDictionary[eventName] += listener;
}
else
{
eventDictionary.Add(eventName, listener);
}
// 如果队列中有待处理的事件,立即触发它们
while (eventQueue.Count > 0 && eventQueue.Peek().EventName == eventName)
{
QueuedEvent queuedEvent = eventQueue.Dequeue();
//发送事件
TriggerEvent(queuedEvent.EventName, queuedEvent.Arg);
}
}
这段代码的话应该很容易理解,字典部分的事件如果有就替换,没有的话就添加。通俗一点呢就像你发了个快递,填的收件人是小红,小红就监听了这个事,这样到货了有短信通知自己(但代码世界里需要监听者自己去主动监听)下面的是个简单的例子
void Start()
{
//监听事件
EventManager.instance.StartListening("快递到了", SetInfo);
}
public void SetInfo(object obj)
{
//根据需要自定义的类型
NextButtonInfo nextButtonInfo = obj as NextButtonInfo;
//自己需要处理的逻辑
......
}
while 循环里面的对列处理就是在所有的队列里查找,有的话移除队列然后发送事件
3 停止监听
//停止监听
public void StopListening(string eventName, Action<object> listener)
{
if (eventDictionary.ContainsKey(eventName))
{
eventDictionary[eventName] -= listener;
}
}
4 发送事件
//发送事件
public void TriggerEvent(string eventName, object arg = null)
{
Action<object> thisEvent;
if (eventDictionary.TryGetValue(eventName, out thisEvent))
{
thisEvent.Invoke(arg);
}
else
{
// 如果没有监听器注册这个事件,将它添加到队列中
eventQueue.Enqueue(new QueuedEvent { EventName = eventName, Arg = arg });
}
}
这段代码呢着重解释下后面的else部分,之所以加这个东西是因为在实践过程中发现个问题,就是我这个事件还没监听呢,你就发送了,就像你发了个快递,已经到地方了,但还没通知收件人,你得找个地方帮他保存着,直到收件人来取货,也就是直到有人去监听事件,然后再去通知他,参数arg是发送事件时传的参数,可仿照下面的例子自定义
NextButtonInfo nextButtonInfo = new NextButtonInfo ();
nextButtonInfo .Title = "标题";
nextButtonInfo .Info = " 内容";
nextButtonInfo .action = () =>
{
//自己的方法
};
EventManager.instance.TriggerEvent("快递到了", summarizeInfo);
这里我把一个自定义的类NextButtonInfo 当做参数发送了出去,当有人监听到快递到了这个名字时,就会获得参数,当然,参数自定义,没有也行。
最后奉上全部代码,欢迎指正:
using System;
using System.Collections.Generic;
using UnityEngine;
public class CustomEventManager : MonoBehaviour
{
public static CustomEventManager instance;
/// <summary>
/// 事件字典
/// </summary>
private Dictionary<string, Action<object>> eventDictionary = new Dictionary<string, Action<object>>();
//事件的队列
private Queue<QueuedEvent> eventQueue = new Queue<QueuedEvent>();
void Awake()
{
if (instance == null)
{
instance = this;
}
else if (instance != this)
{
Destroy(gameObject);
}
}
/// <summary>
/// 监听事件
/// </summary>
/// <param name="eventName"></param>
/// <param name="listener"></param>
public void StartListening(string eventName, Action<object> listener)
{
if (eventDictionary.ContainsKey(eventName))
{
eventDictionary[eventName] += listener;
}
else
{
eventDictionary.Add(eventName, listener);
}
// 如果队列中有待处理的事件,立即触发它们
while (eventQueue.Count > 0 && eventQueue.Peek().EventName == eventName)
{
QueuedEvent queuedEvent = eventQueue.Dequeue();
TriggerEvent(queuedEvent.EventName, queuedEvent.Arg);
}
}
//停止监听
public void StopListening(string eventName, Action<object> listener)
{
if (eventDictionary.ContainsKey(eventName))
{
eventDictionary[eventName] -= listener;
}
}
//发送事件
public void TriggerEvent(string eventName, object arg = null)
{
Action<object> thisEvent;
if (eventDictionary.TryGetValue(eventName, out thisEvent))
{
thisEvent.Invoke(arg);
}
else
{
// 如果没有监听器注册这个事件,将它添加到队列中
eventQueue.Enqueue(new QueuedEvent { EventName = eventName, Arg = arg });
}
}
}
public class QueuedEvent
{
public string EventName { get; set; }
public object Arg { get; set; }
}
如果觉得还可以,点赞评论一下,大家一起共同进步。