H33中的消息机制的使用和原理

H33中的消息机制的使用和原理

目前消息触发分为三类:

  • object接口,使用objs_call触发,监听游戏中所有object的消息触发。
  • 典型的观察者模式,需要手动注册到某个unit中。所有的object都可以通过这种方式监听任何一个unit上的消息。
  • action接口,自动监听所属unit的IID消息,回调信息在action enter时开始生效。

后两种都将消息函数信息存放在unity.ActionManager中,并都使用actions_call回调。

消息机制 监听范围 触发方式 监听信息存放位置 添加接口方式 自动注册 可使用对象 可配置监听次数
object接口 全局游戏 objs_call() objMgr add_interface object 不可以
观察者模式 某个unit actions_call(unit) actionMgr add_observer_interface object 可以
action接口 所属unit actions_call(unit) actionMgr add_action_interfaces action 不可以

先说使用上的区别:

消息机制 监听范围 触发方式 监听信息存放位置 添加接口方式 自动注册 可使用对象 可配置监听次数
object接口 全局游戏 objs_call() objMgr add_interface object 不可以
观察者模式 某个unit actions_call(unit) actionMgr add_observer_interface object 可以
action接口 所属unit actions_call(unit) actionMgr add_action_interfaces action 不可以

1 消息机制的概括介绍

以上三种消息机制,他们的实现都可以分为四个步骤:接口声明,接口注册,监听信息保存以及消息触发。

接口声明在ClientEventInterface中,声明有那些接口以及每个接口有哪些消息处理函数。三种消息机制共用一套消息声明。

接口注册是将object或action添加的接口IID以及实现的接口函数,保存到class中。在这里可以根据IID和funcID找到具体要调用的方法。

监听信息保存是将对监听信息保存到unit中的actionManager中或者全局的objMgr中,在这里可以通过消息的IID找到监听这个消息的所有object或action。

消息触发是根据IID查找监听IID的unit,以及根据funcID去class中的接口信息中找到要调用的函数。

2 使用方法

2.1 添加消息处理函数以及接口类

在ClientEventInterface中预先声明消息,消息处理函数和接口类如下所示

class IOnFuryButtonClick:#一个接口类可以存在多个消息处理函数
    def on_fury_button_click(self, stateID):
        pass
FURY_BUTTON_CLICK = mgr.createIID(IOnFuryButtonClick)

本文称IOnFuryButtonClick为接口类,它可能包含几个接口(消息处理函数),接口类代表着一类消息集合;本文称函数on_fury_button_click为消息处理函数,它代表着一个消息。如果要监听消息,必须监听接口类中的所有消息

2.2 object接口的注册和使用

接口注册和监听信息保存

在某个object中重写函数init_interfaces,使用add_interface添加接口的IID,这个object需要实现接口类中的所有消息处理函数。

def init_interfaces(self):
    if super(FuryAction, self).init_interfaces():
        self.add_interface(G.IID.FURY_BUTTON_CLICK)
        return True
    return False

object在创建时,自动将监听信息保存到ObjectManager中。

消息调用

使用以下代码,则所有实现了该接口的object中的函数on_fury_button_click都会被调用。

G.IID.IOnFuryButtonClick.on_fury_button_click.objs_call(self.furyStateID)

2.3 观察者模式的注册和使用

register_observer可以将object A注册为objectB的某一消息的观察者,当触发objectB的消息时,会调用A中的消息处理函数。

接口注册和监听信息保存

接口注册,重写函数init_observer_interfaces并使用add_observer_interface添加接口IID。


def init_observer_interfaces(self):
    if super(CompUnitManagerAction, self).init_observer_interfaces():
        self.add_observer_interface(G.IID.DEAD)
        return True
    return False

监听信息保存,通过unitA.actionManager.register_observer(G.IID.DEAD,unit_observer,repeatTimes)保存监听信息到actionManager中,将unit_observer作为unitA的观察者,观察unit的IID消息。

消息调用

当消息发生时使用代码G.IID.IDeadHandle.on_dead.actions_call(unitA)即可通知观察unitA的所有观察者,并调用观察者的on_dead消息处理函数。

2.4 action接口注册和监听

action接口的注册只能在action中使用。

接口注册和监听信息保存

接口注册,在action中,重写init_action_interfaces()函数使用add_action_interface注册接口类,action注册接口类需要同时实现接口所拥有的所有消息处理函数。

def init_action_interfaces(self):
    if super(FireEffectAction, self).init_action_interfaces():
        self.add_action_interface(G.IID.ISKILL_APPLY)
        return True
    return False

监听信息保存(此步为自动),当action在enter时,会将action注册到actionManager里面,同时开始监听接口相关的消息。

消息调用

当消息发生,调用G.IID.ISkillApply.on_apply_skill.actions_call(unitA, self.skillID)就会调用unitA中实现了ISKILL_APPLY接口的action中的on_apply_skill函数。

注意,actions_call(unitA)同时触发观察者模式的消息回调和action的接口,首先调用观察unitA的观察者,然后调用unitA中action实现的接口。

3 此模块所依赖的模块

此模块将消息处理接口信息注册到ActionManager和ObjectManager中,只依赖这两个模块的实现。

4 代码原理

下文介绍代码的具体原理,只要记住消息机制分为四个步骤:接口声明,接口注册,监听信息保存以及消息触发,那么就比较容易理解。

4.1 消息声明

声明了接口,在三种机制中都可以使用。

在ClientEventInterface中,预先定义所有的消息处理函数,并将这些处理函数分类,将同一类的消息处理函数作为一个接口类。

interfaceManager给每个接口类分配一个IID,并将接口类及消息处理函数相关信息存放在InterfaceManager中。

在InterfaceManager中根据接口类IID就能获得这个接口类所有的消息处理函数信息。

将每个接口类的接口函数改为指向一个ObjectInterfaceFunctor对象,此对象保存iid信息,消息处理函数ID信息,封装消息函数查找过程等,actions_callobjs_call都属于该对象。

4.2 object接口

object的创建时首先进行接口注册,init_interface调用add_interface根据添加的接口IID,获得接口所有的消息处理函数名,然后根据函数名找到object的对应函数,存放在object.interfaces中,interfaces={iid:{fid:func},...}

object创建同时要注册到ObjectManager中,此时保存监听消息到ObjectManager.actionMap中。

在objs_call中,首先根据IID在ObjectManager中找到监听IID消息的object,然后根据funcId在object.__class__.interfaces中找到对应的函数,然后调用。

4.3 观察者模式

使用object.add_observer_interface(iid)为object进行接口注册,此时将object实现的所有的消息处理函数信息存放在object.__class__observerInterfaces[iid]中,其中函数信息格式为{funcid:func,..}。

使用ActionManager.register_observer(iid,observer,repeatTimes)actionManager.__observers
保存监听iid消息的observer的oid。

actions_call消息触发时,actionManager去查找监听此消息的观察者,根据消息的funid调用观察者的消息处理函数。

4.4 action接口

使用action.add_action_interface(iid)为action进行接口注册,此时将action实现的所有的消息处理函数信息存放在action.__class__.actionInterfaces[iid]中。

在action enter的时候,自动调用actionManager.register_action(action),这时actionManager.__activeActionInterfaceMap保存监听iid消息的action。

actions_call消息触发时,actionManager去查找监听此消息的所有action,根据消息的funid调用action的消息处理函数。

你可能感兴趣的:(H33中的消息机制的使用和原理)