什么是消息机制?
23333333,让我先笑一会。
为什么用消息机制?
三个字,解!!!!耦!!!!合!!!!。
我的框架中的消息机制用例:
1.接收者
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
using
UnityEngine;
using
System.Collections;
using
QFramework;
/// <summary>
/// 1.接收者需要实现IMsgReceiver接口。
/// 2.使用this.RegisterLogicMsg注册消息和回调函数。
/// </summary>
public
class
Receiver : MonoBehaviour,IMsgReceiver {
void
Awake()
{
this
.RegisterLogicMsg (
"Receiver Show Sth"
, ReceiverMsg);
// this.UnRegisterLogicMsg ("Receiver Show Sth", ReceiverMsg);
}
void
ReceiverMsg(
params
object
[] paramList)
{
foreach
(var sth
in
paramList) {
QPrint.Warn (sth.ToString());
}
}
}
|
2.发送者
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
using
UnityEngine;
using
System.Collections;
using
QFramework;
/// <summary>
/// 1.发送者需要,实现IMsgSender接口
/// 2.调用this.SendLogicMsg发送Receiver Show Sth消息,并传入两个参数
/// </summary>
public
class
Sender : MonoBehaviour,IMsgSender {
// Update is called once per frame
void
Update () {
this
.SendLogicMsg (
"Receiver Show Sth"
,
"你好"
,
"世界"
);
}
}
|
3.运行结果
使用起来几行代码的事情,实现起来就没这么简单了。
如何实现的?
可以看到接收者实现了接口IMsgReceiver,发送者实现了接口IMsgSender。 那先看下这两个接口定义。
IMsgReceiver:
[C#]
纯文本查看
复制代码
1
2
3
4
5
6
7
8
9
|
using
UnityEngine;
using
System.Collections;
namespace
QFramework {
public
interface
IMsgReceiver {
}
}
|
IMsgSender:
[C#]
纯文本查看
复制代码
1
2
3
4
5
6
7
8
|
using
UnityEngine;
using
System.Collections;
namespace
QFramework {
public
interface
IMsgSender {
}
}
|
毛都没有啊。也没有SendLogicMsg或者ReceiveLogicMsg方法的定义啊。
答案是使用C# this的扩展方式实现接口方法。 不清楚的童鞋请百度C# this扩展,有好多文章就不介绍了。 以上先告一段落,先介绍个重要的角色,MsgDispatcher(消息分发器)。
贴上第一部分代码:
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
namespace
QFramework {
/// <summary>
/// 消息分发器
/// C# this扩展 需要静态类
/// </summary>
public
static
class
QMsgDispatcher {
/// <summary>
/// 消息捕捉器
/// </summary>
class
LogicMsgHandler {
public
IMsgReceiver receiver;
public
VoidDelegate.WithParams callback;
/*
* VoidDelegate.WithParams 是一种委托 ,定义是这样的
*
* public class VoidDelegate{
* public delegate void WithParams(params object[] paramList);
* }
*/
public
LogicMsgHandler(IMsgReceiver receiver,VoidDelegate.WithParams callback)
{
this
.receiver = receiver;
this
.callback = callback;
}
}
/// <summary>
/// 每个消息名字维护一组消息捕捉器。
/// </summary>
static
Dictionary<
string
,List<LogicMsgHandler>> mMsgHandlerDict =
new
Dictionary<
string
,List<LogicMsgHandler>> ();
|
读注释!!!
贴上注册消息的代码
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
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
|
/// <summary>
/// 注册消息,
/// 注意第一个参数,使用了C# this的扩展,
/// 所以只有实现IMsgReceiver的对象才能调用此方法
/// </summary>
public
static
void
RegisterLogicMsg(
this
IMsgReceiver self,
string
msgName,VoidDelegate.WithParams callback)
{
// 略过
if
(
string
.IsNullOrEmpty(msgName)) {
QPrint.FrameworkWarn(
"RegisterMsg:"
+ msgName +
" is Null or Empty"
);
return
;
}
// 略过
if
(
null
== callback) {
QPrint.FrameworkWarn (
"RegisterMsg:"
+ msgName +
" callback is Null"
);
return
;
}
// 略过
if
(!mMsgHandlerDict.ContainsKey (msgName)) {
mMsgHandlerDict [msgName] =
new
List<LogicMsgHandler> ();
}
// 看下这里
var handlers = mMsgHandlerDict [msgName];
// 略过
// 防止重复注册
foreach
(var handler
in
handlers) {
if
(handler.receiver == self && handler.callback == callback) {
QPrint.FrameworkWarn (
"RegisterMsg:"
+ msgName +
" ayready Register"
);
return
;
}
}
// 再看下这里
handlers.Add (
new
LogicMsgHandler (self, callback));
}
|
为了节省您时间,略过部分的代码就不要看了,什么?!!你都看了!!!! 23333
发送消息相关的代码
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
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
|
/// <summary>
/// 发送消息
/// 注意第一个参数
/// </summary>
public
static
void
SendLogicMsg(
this
IMsgSender sender,
string
msgName,
params
object
[] paramList )
{
// 略过,不用看
if
(
string
.IsNullOrEmpty(msgName)) {
QPrint.FrameworkError(
"SendMsg is Null or Empty"
);
return
;
}
// 略过,不用看
if
(!mMsgHandlerDict.ContainsKey(msgName)){
QPrint.FrameworkWarn(
"SendMsg is UnRegister"
);
return
;
}
// 开始看!!!!
var handlers = mMsgHandlerDict[msgName];
var handlerCount = handlers.Count;
// 之所以是从后向前遍历,是因为 从前向后遍历删除后索引值会不断变化
// 参考文章,http://www.2cto.com/kf/201312/266723.html
for
(
int
index = handlerCount - 1;index >= 0;index--)
{
var handler = handlers[index];
if
(handler.receiver !=
null
) {
QPrint.FrameworkLog (
"SendLogicMsg:"
+ msgName +
" Succeed"
);
handler.callback (paramList);
}
else
{
handlers.Remove (handler);
}
}
}
|
OK主要的部分全都贴出来啦
以上代码以全部上传到Github上边
贴出代码地址:消息机制相关代码地址:https://github.com/liangxiegame/QFramework/tree/master/Script/Event
可以改进的地方:
1.目前整个游戏的消息都由一个字典维护,可以改进为每个模块维护一个字典或者其他方式。
2.消息名字类型由字符串定义的,可以改成枚举转unsigned int方式。
3.欢迎补充。
坑
1.如果是MonoBehaviour注册消息之后,GameObject Destroy之前一定要注销消息,之前的解决方案是,自定义一个基类来维护该对象已经注册的消息列表,然后在基类的OnDestory时候遍历卸载。
2.欢迎补充。
附:我的框架地址:https://github.com/liangxiegame/QFramework
转载请注明地址:凉鞋的笔记:http://liangxiegame.com/