最近做项目用到消息机,去网上找了找发现很多不错的,可是都是即时传送,没有延迟功能。自己就写了一个带延迟的消息机。
文中的消息机基于wiki上的一个消息机,就不过多说明了,大家可以参考这个:http://wiki.unity3d.com/index.php/Advanced_CSharp_Messenger
关于延迟功能,最开始打算用协程去写,后来发现unity3d很多方法和值只能在主线程中使用,所以单写了一个闹钟类,用来计算时间。
大体思路就是延迟消息传入到闹钟类并排序,闹钟类的update方法进行判断,如果延迟消息时间到了,就发送消息。
下面说一下主要功能的实现
延迟消息类,类里包含延迟的时间,收听者名称和委托的参数
///
/// 延迟消息类
///
public class DelayMessage {
//延迟时间
public float delayTime;
//收听者
public string lis;
//参数
public object o;
//构造函数
public DelayMessage(string lis, object o,float delayTime)
{
this.lis = lis;
this.o=o;
//传递的时间为需要延迟的时间 这里加上当前时间
this.delayTime = delayTime+Time.time;
}
}
//延迟消息
public static void Broadcase(string lis, T arg0,float timeDelay)
{
//将事件加入延迟事件队列
TimeClock.AddClock( new DelayMessage(lis, arg0,timeDelay));
}
//闹钟
static List clockQueue = new List(100);
//添加闹钟
public static void AddClock(DelayMessage dm)
{
//添加闹钟
clockQueue.Add( dm);
//排序
clockQueue = (from entry in clockQueue orderby entry.delayTime ascending select entry).ToList();
//获得最小时间
firstKeysSort();
}
将延迟的消息加入到集合中 ,并且用linq进行排序,排序依据为delayTime。
firstKeySort方法:
//最小时间
private static float firstKey;
//最小时间集合 有多个最小时间时出现
private static List firstKeys;
//获得最小时间集合
private static void firstKeysSort() {
if (clockQueue.Count == 0)
return;
//取最小时间
firstKey = (from d in clockQueue orderby d.delayTime ascending select d.delayTime).First();
if(firstKeys!=null)
firstKeys.Clear();
// 最小时间可能为多个 所以用集合存储最小时间
firstKeys = (from d in clockQueue where d.delayTime == firstKey select d.delayTime).ToList();
}
因为可能会在同一时间传入多个延迟时间相同的消息,所以使用一个集合来记录离当前时间最近的延迟时间
void Update()
{
//如果没有闹钟返回
if (clockQueue.Count == 0)
return;
////闹钟时间到
if (Time.time >= firstKeys[0])
{
foreach (float t in firstKeys) {
//发送延迟消息
DelayMessage dm = clockQueue[0];
NotificationCenter.Broadcase(dm.lis, dm.o);
//移除闹钟
clockQueue.Remove(clockQueue[0]);
}
//重新获得最小时间
firstKeysSort();
}
}
时间到后会发送消息,发送完后移除消息集合中的消息,同时重新计算下一个最小时间。
注:初学者,可能有不对之处希望大家指正。消息类还没有完善,如果场景转换的话可能得重置收听者,如果以后有时间会完善。