-
Notifications
You must be signed in to change notification settings - Fork 46
/
Copy pathEventQueuePattern.cs
354 lines (295 loc) · 11.1 KB
/
EventQueuePattern.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
namespace EventQueuePattern
{
public class EventQueuePattern : MonoBehaviour
{
// Use this for initialization
void Start()
{
//添加对"START"信息标识的监听,收到信息后触发OnReceiveMessageHandler处理。
MessageDispatcher.AddListener("START", OnReceiveMessageHandler);
//添加对"START"与指定了"Filter"过滤标识信息的监听,收到拥有"START"信息标识和"Filter"过滤标识信息的发送后触发OnReceiveMessageHandler处理。
MessageDispatcher.AddListener("START", OnReceiveMessageHandler, "Filter");
//添加对"Custom"信息标识的监听,收到信息后触发OnReceiveMessageHandler处理。
MessageDispatcher.AddListener("Custom", OnReceiveCustomMessageHandler);
Debug.Log("初始化成功,请按键盘上1,2,3数字键进行消息发送。");
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Alpha1))
{
Message sMessage = new Message();
sMessage.Type = "START";
sMessage.Filter = "Filter";
sMessage.Data = "你好,我是有过滤标识的信息";
//MessageDispatcher发送一条信息出去,信息的标识为"START",过滤标识为"Filter"。
MessageDispatcher.SendMessage(sMessage);
}
if (Input.GetKeyDown(KeyCode.Alpha2))
{
Message sMessage = new Message();
sMessage.Type = "START";
sMessage.Data = "你好~~~我是一条延迟发送的消息";
//延迟1秒后才发送
sMessage.Delay = 1f;
//MessageDispatcher发送一条信息出去,信息的标识为"START"。
MessageDispatcher.SendMessage(sMessage);
}
if (Input.GetKeyDown(KeyCode.Alpha3))
{
MyCustomMessage mcm = new MyCustomMessage();
mcm.MyCustomString = "我是自定义消息的额外数据";
mcm.Type = "Custom";
MessageDispatcher.SendMessage(mcm);
}
}
/// <summary>
/// 消息接收者
/// </summary>
/// <param name="sMessage"></param>
private void OnReceiveMessageHandler(IMessage sMessage)
{
Debug.Log(sMessage.Data.ToString());
}
private void OnReceiveCustomMessageHandler(IMessage sMessage)
{
Debug.Log((sMessage as MyCustomMessage).MyCustomString);
}
}
/// <summary>
/// 自定义的消息
/// </summary>
public class MyCustomMessage : Message
{
public string MyCustomString;
}
/// <summary>
/// Message类相关信息的接口,就好像一条短信一样或者一个通知一样。
/// Message由MessageDispatcher类发送到监听对应信息者的对象中去。
/// 对象可以通过MessageDispatcher类传递一个命令或者一些数据给另一个或多个监听对应信息的类。
/// 可通过继承此接口自定义自己传递的数据信息
/// </summary>
public interface IMessage
{
/// <summary>
/// 信息的标识,可以是任何值
/// </summary>
string Type { get; set; }
/// <summary>
/// 监听者的信息过滤标识
/// </summary>
string Filter { get; set; }
/// <summary>
/// 信息发送的延迟时间,单位为秒
/// </summary>
float Delay { get; set; }
/// <summary>
/// 信息的核心数据
/// </summary>
object Data { get; set; }
/// <summary>
/// 定义信息是否已发送
/// </summary>
bool IsSent { get; set; }
/// <summary>
/// 重置这个信息实例
/// </summary>
void Reset();
}
/// <summary>
/// 消息的基类
/// </summary>
public class Message : IMessage
{
protected object mData = null;
public object Data
{
get { return mData; }
set { mData = value; }
}
protected float mDelay = 0;
public float Delay
{
get { return mDelay; }
set { mDelay = value; }
}
protected bool mIsSent = false;
public bool IsSent
{
get { return mIsSent; }
set { mIsSent = value; }
}
protected string mType = String.Empty;
public string Type
{
get { return mType; }
set { mType = value; }
}
protected string mFilter = String.Empty;
public string Filter
{
get { return mFilter; }
set { mFilter = value; }
}
public void Reset()
{
mType = String.Empty;
mData = null;
mIsSent = false;
mFilter = string.Empty;
mDelay = 0.0f;
}
}
/// <summary>
/// 用来给监听信息者收到信息后执行的处理。
/// </summary>
/// <param name="rMessage"></param>
public delegate void MessageHandler(IMessage rMessage);
/// <summary>
/// 消息分发管理管理类
/// </summary>
public class MessageDispatcher
{
/// <summary>
/// 创建MessageDispatcher在Unity的存根,专门处理延迟信息的发送
/// </summary>
private static MessageDispatcherStub sStub = (new GameObject("MessageDispatcherStub")).AddComponent<MessageDispatcherStub>();
/// <summary>
/// 当某些信息没有监听的时候,信息发送的处理由该委托处理。
/// </summary>
public static MessageHandler MessageNotHandled = null;
/// <summary>
/// 存储标识着延迟发送的信息
/// </summary>
private static List<IMessage> mMessages = new List<IMessage>();
/// <summary>
/// 主要存储信息对应的处理
/// 第一个string是信息的标识,第二个string是监听过滤信息的标识,第三个是信息发送成功的处理
/// </summary>
private static Dictionary<string, Dictionary<string, MessageHandler>> mMessageHandlers = new Dictionary<string, Dictionary<string, MessageHandler>>();
/// <summary>
/// 清除所有延迟信息的列表
/// </summary>
public static void ClearMessages()
{
mMessages.Clear();
}
/// <summary>
/// 添加一个对信息的监听
/// </summary>
/// <param name="rMessageType">所监听信息的标识</param>
/// <param name="rFilter">所监听信息过滤的标识</param>
/// <param name="rHandler">所监听信息后的处理,即信息由派送者发出去后的处理</param>
public static void AddListener(string rMessageType, MessageHandler rHandler, string rFilter = "")
{
Dictionary<string, MessageHandler> lRecipientDictionary = null;
//查找信息对应处理的列表里是否包含了这个信息,若包含取出他的对应的过滤和处理。
if (mMessageHandlers.ContainsKey(rMessageType))
{
lRecipientDictionary = mMessageHandlers[rMessageType];
}
//如果没有包含这个信息处理的标识则创建他
else
{
lRecipientDictionary = new Dictionary<string, MessageHandler>();
mMessageHandlers.Add(rMessageType, lRecipientDictionary);
}
//检查信息过滤集合是否包含了过滤信息的标识,""代表没有过滤标识
if (!lRecipientDictionary.ContainsKey(rFilter))
{
lRecipientDictionary.Add(rFilter, null);
}
//因为是引用,所以会自动更新到mMessageHandlers里。
lRecipientDictionary[rFilter] += rHandler;
}
/// <summary>
/// 发送信息出去
/// </summary>
/// <param name="rMessage"></param>
public static void SendMessage(IMessage rMessage)
{
//是否丢失接收信息的监听者,默认为true
bool lReportMissingRecipient = true;
//如果信息有延迟时间则把该信息加入到延迟信息列表中等待触发。
if (rMessage.Delay > 0)
{
if (!mMessages.Contains(rMessage))
{
mMessages.Add(rMessage);
}
//避免触发下面的丢失监听者代码块
lReportMissingRecipient = false;
}
//没有延迟的话直接看看信息相应处理列表是否包含这条信息
else if (mMessageHandlers.ContainsKey(rMessage.Type))
{
//得到相应信息的处理
Dictionary<string, MessageHandler> lHandlers = mMessageHandlers[rMessage.Type];
//遍历相信信息的过滤的标识
foreach (string lFilter in lHandlers.Keys)
{
if (lHandlers[lFilter] == null)
{
continue;
}
if (lFilter.Equals(rMessage.Filter))
{
lHandlers[lFilter](rMessage);
rMessage.IsSent = true;
lReportMissingRecipient = false;
}
}
}
if (lReportMissingRecipient)
{
if (MessageNotHandled == null)
{
Debug.LogWarning(string.Format("MessageDispatcher无法识别Message.Type:{0} 或者是信息过滤指定的Message.Filter", rMessage.Type, rMessage.Filter));
}
else
{
MessageNotHandled(rMessage);
}
}
}
/// <summary>
/// 在每帧中负责处理延迟信息列表的发送
/// </summary>
public static void Update()
{
//处理延迟信息列表的信息发送
for (int i = 0; i < mMessages.Count; i++)
{
IMessage lMessage = mMessages[i];
// 减少延迟时间
lMessage.Delay -= Time.deltaTime;
if (lMessage.Delay < 0) { lMessage.Delay = 0; }
// 如果到时间了就立即发送
if (!lMessage.IsSent && lMessage.Delay == 0)
{
SendMessage(lMessage);
mMessages.RemoveAt(i);
}
}
}
}
public sealed class MessageDispatcherStub : MonoBehaviour
{
void Awake()
{
DontDestroyOnLoad(gameObject);
}
void Update()
{
MessageDispatcher.Update();
}
public void OnDisable()
{
MessageDispatcher.ClearMessages();
}
}
}