C#Unity框架

在Unity中自定义一个自己的事件分发系统EventDispatcher(原理篇)

Spread the love

随着游戏工程的越来越大,项目中不同模块的耦合程度也越来越紧密。多人合作编程的时候经常需要了解别人的模块,造成了诸多问题,导致迭代速度减慢。
事件分发机制就是为了解决这个问题而产生的。

举个简单的例子:

有两个模块A,A模块负责了一块重要核心逻辑。
就例如是游戏中人物血量的计算。

在游戏当中,玩家受到了攻击、Debuff等等与血量相关的操作都会对A模块进行操作。

那么这个时候,我们说我们的血量模块和这些模块是耦合的。
有一天,策划忽然想到一个点子,希望将血量的修改改变为先减少玩家的护盾,然后再对血量进行计算。
那么我们的A模块就需要受到修改
这套方案我们叫其模块C,我们已经将A封装到C当中了,但是这些减血模块的引用依旧在A上,那么我们就不得不一个个得去修改引用,而转而去调用C模块。

假设我们有10000个修改血量的地方,那么就意味着我们需要修改10000个地方,这个时候我们似乎已经无法通过修改引用的方案来进行修改系统,只能重新编写A系统来适应C的方案。
这将大大减慢我们的迭代速度。程序员们只能加班加班再加班。

但是,如果我们使用了另外一套机制,却依旧需要保留模块A的时候,我们就无法通过重新编写A来解决该问题,因为需要顾及还需要用到A的模块。
真的是太麻烦了!

所以提出了事件机制,这一机制在各个模块解耦中扮演着重要的角色,并且在后面我们会讲到其在MVC中的重要地位。

我们继续通过画图来解释:
我们这一次通过一个中介者,事件分发器来进行调用,调用者需要向事件分发者发送一条消息,然后事件分发器通过这条消息来判断给哪个对象发送消息。

讲到这里我们其实可以想起两种经典的设计模式:一种是观察者模式、另一种是调停者模式。
我们的对象A首先告诉中介者:如果有修改血量的消息的话那就告诉我!
然后其他所有的调用者(假设还是10000个)需要修改血量的时候就告诉中介者:我要修改血量!不管是谁!反正能改就行了!(如果需要参数的话顺便把参数也给他)
中介者看一看手上的记录,点点头:确实是有人委托我看着有没有人投递这条消息。
中介者这时就将消息告诉对象A(此时修改血量的调用者完全不知道A的存在)
对象A接受任务!修改血量!最终调用完成了。

到这里为止,我们所完成的事情与前面所做的事情似乎没有任何区别。
其实区别已经开始出现了:调用者对实际操作者并没有进行直接的接触。
这意味着A与调用者们是完全解耦状态的!
只需要大家都知道修改血量这一操作就可以了。

那么这个时候,策划说,我们要改系统了!现在要先扣护甲再扣血!

这个时候任务就从A的身上卸下,给到了C的身上。

这个时候我们只需要删除A向中介者发布委托的代码,转而将发布委托的代码放到C的身上就好了。
我们需要修改的并不是B与其他的所有调用者,而仅仅是发布委托的对象而已。

这个时候我们的真正目的就达到了!

当然除了多对一以外,多对一和多对多也是同样适用的。

比如,我们的金钱系统,在主界面上需要显示,在玩家装备界面上需要显示,还有N个界面上需要显示:

这其实就形成了一种数据捆绑:一旦数据发生改变就将消息发布给所有需要用到的界面。界面也会相应地发生改变。
在OC中的KVO、还有PureMVC其实用到的也都是一样的原理。
无非就是通过一个中介者来将耦合全部集中到中介者身上(对KVO来说甚至不存在中介者这个玩意儿,因为这东西已经在底层生成了)。

那么理所当然的,我们可以用C#来实现这套系统,更加可以放到我们的Unity项目当中。
在本篇文章中仅仅讲解原理,在实现篇中会将完整的实现过程呈现给大家!

**如果想直接看源代码的话可以查看我的Unity增强库工程
**https://github.com/vgvgvvv/ResetCore.git
**事件分发器的目录在Asset/ResetCore/Core/Events当中。
除了最基本的事件分发之外还有很多的扩展功能,有兴趣的话可以看一看。

当然我相信还有更好的事件系统,像AssetStore上面有卖25刀的事件分发器,我是没买,不知道人家写得怎么样。

明天就要上班了~真的不想上班呀~

发表评论

电子邮件地址不会被公开。 必填项已用*标注